
On Thursday 07 February 2008, Don Stewart wrote:
This function is typically defined once per project. So its about time this safe variant of 'read' made it into the base.
maybeRead :: Read a => String -> Maybe a maybeRead s = case reads s of [(x, "")] -> Just x _ -> Nothing
Consideration period: 1 week.
Patch to Text.Read attached.
I was poking around the GHC sources, and it seems like you'd be closer to 'read' if you went with: maybeRead s = case reads s of [(x, s')] | all isSpace s' -> Just x _ -> Nothing I'd also, personally, vote in favor of readM. fail is a wart, but that's a problem with the Monad class, not with the idea of failing in an arbitrary, appropriate monad. In fact, if you use fail, you can also make a distinction between "no parse" and "ambiguous parse", as read does. In fact, GHC has an internal 'readEither' it uses to define 'read': readEither s = case [ x | (x,"") <- readPrec_to_S read' minPrec s ] of [x] -> Right x [] -> Left "Prelude.read: no parse" _ -> Left "Prelude.read: ambiguous parse" where read' = do x <- readPrec lift P.skipSpaces return x Using this auxiliary function, you have: read s = either error id (readEither s) maybeRead s = either (const Nothing) Just (readEither s) readIO s = either fail return (readEither s) -- [1] readM s = either fail return (readEither s) readM is the generalization of readIO, maybeRead, and even readEither, so one could simply define it instead of readEither, read in terms of readM, and export both (although I don't know how that'd gel with non-GHC compilers; the importing/exporting in base is somewhat convoluted :)). -- Dan 1: readIO apparently uses 'lex' instead of 'skipSpaces', which is the same if there are actually just spaces left, but does extra work if not.