Proposal: Add Text.Read.maybeRead :: Read a => String -> Maybe a
Dan Doel
dan.doel at gmail.com
Fri Feb 8 01:48:50 EST 2008
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.
More information about the Libraries
mailing list