Quantcast

Proposal: Add Text.Read.maybeRead :: Read a => String -> Maybe a

classic Classic list List threaded Threaded
32 messages Options
12
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Proposal: Add Text.Read.maybeRead :: Read a => String -> Maybe a

Don Stewart-2
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.


_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries

maybeRead.patch (78K) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Proposal: Add Text.Read.maybeRead :: Read a => String -> Maybe a

Henning Thielemann

On Thu, 7 Feb 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.

Seems to be useful. May prevent people from using just 'read' while hoping
that parsing will always succeed.
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Proposal: Add Text.Read.maybeRead :: Read a => String -> Maybe a

Jeff Polakow
In reply to this post by Don Stewart-2

Hello,

Why not allow an arbitrary monad?

readM :: (Monad m, Read a) => String -> String -> m a
readM errMsg s = case reads s of
    [(x, "")] -> return x
    _ -> fail errMsg

-Jeff


[hidden email] wrote on 02/07/2008 01:46:48 PM:

> 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.
>
> [attachment "maybeRead.patch" deleted by Jeff Polakow/db/dbcom]
> _______________________________________________
> Libraries mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/libraries

---

This e-mail may contain confidential and/or privileged information. If you
are not the intended recipient (or have received this e-mail in error)
please notify the sender immediately and destroy this e-mail. Any
unauthorized copying, disclosure or distribution of the material in this
e-mail is strictly forbidden.

_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Proposal: Add Text.Read.maybeRead :: Read a => String -> Maybe a

Iavor Diatchki
Hello,
I don't think that the function should be in an arbitrary monad
because not all monads support failure, and the purpose of using this
function is to take an action when a parse error occurs (if parse
errors were not an issue, then we could just use 'read' instead).  If
we really wanted to generalize the function, then we should use the
'MonadPlus' (or 'Alternative') classes to restrict the result to types
that have meaningful "default" values.   Having said this, I have used
this function on many occasions, and the Maybe type has always been
sufficient, so my preference would be to keep the original type that
was proposed by Don.
-Iavor


2008/2/7 Jeff Polakow <[hidden email]>:

>
> Hello,
>
> Why not allow an arbitrary monad?
>
> readM :: (Monad m, Read a) => String -> String -> m a
> readM errMsg s = case reads s of
>     [(x, "")] -> return x
>     _ -> fail errMsg
>
> -Jeff
>
>
> [hidden email] wrote on 02/07/2008 01:46:48 PM:
>
>
>
>  > 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.
>  >
>  > [attachment "maybeRead.patch" deleted by Jeff Polakow/db/dbcom]
>
>  > _______________________________________________
>  > Libraries mailing list
>  > [hidden email]
>  > http://www.haskell.org/mailman/listinfo/libraries
>
>  ---
>
>  This e-mail may contain confidential and/or privileged information. If you
>  are not the intended recipient (or have received this e-mail in error)
>  please notify the sender immediately and destroy this e-mail. Any
>  unauthorized copying, disclosure or distribution of the material in this
>  e-mail is strictly forbidden.
> _______________________________________________
> Libraries mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/libraries
>
>
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Proposal: Add Text.Read.maybeRead :: Read a => String -> Maybe a

Neil Mitchell
In reply to this post by Don Stewart-2
Hi

> This function is typically defined once per project. So its
> about time this safe variant of 'read' made it into the base.

It's also in the Safe library as readMay:
http://www-users.cs.york.ac.uk/~ndm/safe/ and has been useful. Not
100% certain that maybe read is the right name as opposed to readMaybe
- given read/reads both have a read prefix.

(+0.7) agreement.

Thanks

Neil
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Proposal: Add Text.Read.maybeRead :: Read a => String -> Maybe a

Ross Paterson
In reply to this post by Don Stewart-2
On Thu, Feb 07, 2008 at 10:46:48AM -0800, 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

I think this is a good idea, though I normally write the equivalent of

      maybeRead :: Read a => String -> Maybe a
      maybeRead s = case reads s of
          [(x, rest)] | all isSpace rest -> Just x
          _         -> Nothing

and would prefer not to generalize it to any monad.  fail is a wart,
not a design pattern.

> Consideration period: 1 week.

I think that's too short, and the recent fashion of 2 weeks is too short,
even for an uncontroversial change.  Some people aren't here continuously,
but I'd still like to get their input.
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Proposal: Add Text.Read.maybeRead :: Read a => String -> Maybe a

John Meacham
In reply to this post by Don Stewart-2
On Thu, Feb 07, 2008 at 10:46:48AM -0800, 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.


May I suggest 'readM'?

It is just the obvious generalization of the 'readIO' that is in the
Prelude, that it isn't generalized is a bug in the prelude IMHO. (and it
is signifigantly more useful)

>     readM :: (Monad m,Read a) => String -> m a
>     readM s = case reads s of
>         [(x, "")] -> return x
>         _         -> fail "readM: no parse"


        John

--
John Meacham - ⑆repetae.net⑆john⑈
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Proposal: Add Text.Read.maybeRead :: Read a => String -> Maybe a

John Meacham
In reply to this post by Jeff Polakow
On Thu, Feb 07, 2008 at 03:20:31PM -0500, Jeff Polakow wrote:
> Why not allow an arbitrary monad?
>
> readM :: (Monad m, Read a) => String -> String -> m a
> readM errMsg s = case reads s of
>     [(x, "")] -> return x
>     _ -> fail errMsg

Yes. I strongly support this, this routine has been in my GenUtil for a
long time as is hella useful. Though, I wouldn't give it an error
message argument and just let it have something descriptive like "readM:
no parse" as in my other reply.

        John


--
John Meacham - ⑆repetae.net⑆john⑈
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Proposal: Add Text.Read.maybeRead :: Read a => String -> Maybe a

David Menendez-2
In reply to this post by Ross Paterson
On Feb 7, 2008 6:12 PM, Ross Paterson <[hidden email]> wrote:
> I think this is a good idea, though I normally write the equivalent of
>
>       maybeRead :: Read a => String -> Maybe a
>       maybeRead s = case reads s of
>           [(x, rest)] | all isSpace rest -> Just x
>           _         -> Nothing
>
> and would prefer not to generalize it to any monad.  fail is a wart,
> not a design pattern.

I also prefer Maybe to fail. Error strings are only useful if you're
ignoring them or passing them to the user without interpretation.

--
Dave Menendez <[hidden email]>
<http://www.eyrie.org/~zednenem/>
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Proposal: Add Text.Read.maybeRead :: Read a => String -> Maybe a

sclv
In reply to this post by John Meacham
readM for an arbitrary monad with a standard error message++. not  
necessarily because I believe this is the right or even the one true  
way to do this per se., but rather because this is how Data.Map etc.  
handle failure on lookups, etc. Given that read apparently trims  
trailing whitespace, I also approve of adding that to this function.  
My argument here is that uniform and expected behavior should be a  
stronger goal of libraries than the ugly rails notion of  
"configuration by convention." As such, generalizing to an arbitrary  
monad is more uniform and common than simply using a Maybe instance  
(and provides a strict superset of functionality to boot).  
Furthermore, I agree with the dislike of fail, and agree that it  
should be moved to MonadFail or MonadZero or such. However, I also  
think that even if this were to happen in a major revamp (Haskell' or  
whatever) that it would be more appropriate to have a generalized  
readM than not. in fact, as a whole, there's really no reason the  
libraries should err on the size of giving less generality rather  
than more.

--Sterl.

p.s. Actually, the fact that read doesn't act like readM by default  
strikes me as a bug, but not one that can reasonably be resolved with  
the libraries as they stand. As the general sentiment seems to go,  
total base libraries ftw. The more direct the path for haskell  
newcomers to come over the benefits of strong type-safety in all  
instances, the better.

On Feb 7, 2008, at 10:52 PM, John Meacham wrote:

> On Thu, Feb 07, 2008 at 03:20:31PM -0500, Jeff Polakow wrote:
>> Why not allow an arbitrary monad?
>>
>> readM :: (Monad m, Read a) => String -> String -> m a
>> readM errMsg s = case reads s of
>>     [(x, "")] -> return x
>>     _ -> fail errMsg
>
> Yes. I strongly support this, this routine has been in my GenUtil  
> for a
> long time as is hella useful. Though, I wouldn't give it an error
> message argument and just let it have something descriptive like  
> "readM:
> no parse" as in my other reply.
>
>         John
>
>
> --
> John Meacham - ⑆repetae.net⑆john⑈
> _______________________________________________
> Libraries mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Proposal: Add Text.Read.maybeRead :: Read a => String -> Maybe a

Dan Doel
In reply to this post by Don Stewart-2
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.
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Proposal: Add Text.Read.maybeRead :: Read a => String -> Maybe a

Henning Thielemann
In reply to this post by Iavor Diatchki

On Thu, 7 Feb 2008, Iavor Diatchki wrote:

> Hello,
> I don't think that the function should be in an arbitrary monad
> because not all monads support failure, and the purpose of using this
> function is to take an action when a parse error occurs

I'm for the fixed Maybe type. I also think that 'maybeRead' is better than
'readMaybe' since the latter one suggests that it is about reading a value
of type 'Maybe'. (Though you can also argue the opposite way.)
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Proposal: Add Text.Read.maybeRead :: Read a => String -> Maybe a

Johannes Waldmann
Hello. I like the functionality,
but I generally don't like type information in a name.
Isn't there a way to express this with the
module system or the type system.
Best regards, Johannes.
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Proposal: Add Text.Read.maybeRead :: Read a => String -> Maybe a

Johan Tibell-2
On Feb 8, 2008 9:05 AM, Johannes Waldmann <[hidden email]> wrote:
> Hello. I like the functionality,
> but I generally don't like type information in a name.
> Isn't there a way to express this with the
> module system or the type system.
> Best regards, Johannes.

I have to agree here. We should try to make more use of the module
system and qualified imports. All this type information in function
names is distracting.

And no fail please.

-- Johan
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Proposal: Add Text.Read.maybeRead :: Read a => String -> Maybe a

Jules Bean
In reply to this post by Dan Doel
Dan Doel wrote:
>     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"

Because there are multiple error cases, I support the Monad version.

I agree with everyone who has said that fail is a wart, but since we
don't have a haskell98 'MonadStringError', and 'MonadError' requires
fundeps and MPTCs, I think fail is the best we have at the moment.

If we were prepared to endorse fundeps and MPTCs then I might support a
(Error e, MonadError e m,Read a) => String -> m a type.

If there was only one error case, then Maybe would contain enough
information, and I would support the simpler version. As there are three
(no parse, ambiguous parse, and incomplete parse), it is losing
information just to product Nothing.

+1 for Text.Read.readM from me.

Dan points out in conversation that a MonadPlus constraint might be
considered a 'valid hint' that fail is a sensible operation.

Without wishing to derail the conversation, common combinators to
promote and demote error types might be good thigns to document and
possibly even include in the standard lib. One example which springs to
mind is

maybe (fail "it went wrong") return

which the combinator to "promote" from unlabelled errors (Maybe) to
labelled errors (presumably in an error monad). Or with a custom error
type, something like

maybe (throwError ThereWasAProblem) return

which could be set up as an infix like this:

possiblyFailingOperation `withError` ThereWasAProblem

There are a whole bunch of tricks like this for embedding one error
strategy inside another which are 'obvious' and even 'folklore' but not
written down.

Jules


_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Proposal: Add Text.Read.maybeRead :: Read a => String -> Maybe a

John Meacham
In reply to this post by David Menendez-2
On Fri, Feb 08, 2008 at 12:17:31AM -0500, David Menendez wrote:

> On Feb 7, 2008 6:12 PM, Ross Paterson <[hidden email]> wrote:
> > I think this is a good idea, though I normally write the equivalent of
> >
> >       maybeRead :: Read a => String -> Maybe a
> >       maybeRead s = case reads s of
> >           [(x, rest)] | all isSpace rest -> Just x
> >           _         -> Nothing
> >
> > and would prefer not to generalize it to any monad.  fail is a wart,
> > not a design pattern.
>
> I also prefer Maybe to fail. Error strings are only useful if you're
> ignoring them or passing them to the user without interpretation.

say that next time you get a mysterious "fromJust: Nothing" error with
no context, error messages in haskell are quite an issue as is, _any_
useful information is good, passing them on to the user without
interpretation is loads better than not having any clue what went wrong.
It is what you want to do because the fact that it was a 'readM' that
failed is extremely useful for figuring out what went wrong. It is a
straightforward generalization that is very useful pragmatically.

    John

--
John Meacham - ⑆repetae.net⑆john⑈
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Proposal: Add Text.Read.maybeRead :: Read a => String -> Maybe a

Henning Thielemann

On Fri, 8 Feb 2008, John Meacham wrote:

> On Fri, Feb 08, 2008 at 12:17:31AM -0500, David Menendez wrote:
>
> > I also prefer Maybe to fail. Error strings are only useful if you're
> > ignoring them or passing them to the user without interpretation.
>
> say that next time you get a mysterious "fromJust: Nothing" error with
> no context, error messages in haskell are quite an issue as is, _any_
> useful information is good, passing them on to the user without
> interpretation is loads better than not having any clue what went wrong.

Since 'error' denotes a programming error, not an exception, there is no
need that the user understands the error message. It is entirely the task
of the programmer to understand the message or its absence and it would
be completely ok if the program aborts with "the programmer made a
mistake, please complain to him".
 http://www.haskell.org/haskellwiki/Error
 http://www.haskell.org/haskellwiki/Exception
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Proposal: Add Text.Read.maybeRead :: Read a => String -> Maybe a

Yitzchak Gale
In reply to this post by Ross Paterson
I vote mildly in favor of maybeRead,
strongly against readM.

"fail" refers only to failure of pattern matching.
The wart is that its name should have been
more specific, like "patternFail". Using
"fail" for a non-pattern-matching error is a
bug, not just a wart, in my opinion.

My preferences for the type of this function,
from best to worst, would be:

1. (Error e, MonadError e m, Read a) => String -> m a
2. (MonadZero m, Read a) => String -> m a
3. (MonanPlus m, Read a) => String -> m a
4. Read a => String -> Maybe a

But (1) depends on mtl, and MonadZero is
not even part of the libraries, so (2) is also out.

That leaves (3) and (4) as the only possibilities.
They're still useful sometimes.

Thanks,
Yitz
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Proposal: Add Text.Read.maybeRead :: Read a => String -> Maybe a

Aaron Denney
On 2008-02-08, Yitzchak Gale <[hidden email]> wrote:
> I vote mildly in favor of maybeRead,
> strongly against readM.
>
> "fail" refers only to failure of pattern matching.
> The wart is that its name should have been
> more specific, like "patternFail". Using
> "fail" for a non-pattern-matching error is a
> bug, not just a wart, in my opinion.

Even if you do consider it a bug, it's an extremely useful bug.
I don't see the point in deprecating it until a truly usable alternative
is actually in the standard.

--
Aaron Denney
-><-

_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Proposal: Add Text.Read.maybeRead :: Read a => String -> Maybe a

John Meacham
In reply to this post by Henning Thielemann
On Fri, Feb 08, 2008 at 11:39:18AM +0100, Henning Thielemann wrote:

> > say that next time you get a mysterious "fromJust: Nothing" error with
> > no context, error messages in haskell are quite an issue as is, _any_
> > useful information is good, passing them on to the user without
> > interpretation is loads better than not having any clue what went wrong.
>
> Since 'error' denotes a programming error, not an exception, there is no
> need that the user understands the error message. It is entirely the task
> of the programmer to understand the message or its absence and it would
> be completely ok if the program aborts with "the programmer made a
> mistake, please complain to him".
>  http://www.haskell.org/haskellwiki/Error
>  http://www.haskell.org/haskellwiki/Exception

I am not sure what distinction you are making between the user and the
developer. I don't believe errors should be catchable at all and find
the ability to catch 'error' rather unaethetic. But I do believe they
should be absolutely as informative as possible in order to track down
bugs and the string argument is invaluable for that. I am not saying
that "users" will be happier seeing "readM: no parse" than "fromJust:
Nothing" as they both indicate bugs in your code, but getting a bug
report with the first is much more useful and more precise. Haskell is
hard enough to debug as is, we should take help wherever we can get it.

        John


--
John Meacham - ⑆repetae.net⑆john⑈
_______________________________________________
Libraries mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/libraries
12
Loading...