Errors in non-monadic code

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
17 messages Options
Reply | Threaded
Open this post in threaded view
|

Errors in non-monadic code

Jose A. Lopes
Hi,

What is the proper way to implement a non-monadic function that checks
whether a given value is correct and gives a proper error message
otherwise ? What is the recommended option ?

* Either String a

check val
  | valid val = Right val
  | otherwise = Left errorMsg


* Maybe String

check val
  | valid val = Nothing
  | otherwise = Just errorMsg


Cheers,
Jose

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Errors in non-monadic code

Daniil Frumin

On Mon, Aug 19, 2013 at 9:48 PM, <[hidden email]> wrote:
Hi,


Hello!
 
What is the proper way to implement a non-monadic function that checks
whether a given value is correct and gives a proper error message
otherwise ? What is the recommended option ?

I am not sure, what do you mean by non-monadic. Both (Either String) and Maybe are monads.

You can pick up whatever option you like, depending on which option, in your opinion, suits you better for your specific case.
There is also a helpful errors [1] package that provide convenient means of converting between the results of the two approaches.

Control.Error.Util.hush :: Either a b -> Maybe b
Control.Error.Util.note :: a -> Maybe b -> Either a b
 
* Either String a

check val
  | valid val = Right val
  | otherwise = Left errorMsg


* Maybe String

check val
  | valid val = Nothing
  | otherwise = Just errorMsg


Cheers,
Jose

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe

[1] http://hackage.haskell.org/package/errors

--
Sincerely yours,
-- Daniil

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Errors in non-monadic code

Brandon Allbery
In reply to this post by Jose A. Lopes
On Mon, Aug 19, 2013 at 1:48 PM, <[hidden email]> wrote:
What is the proper way to implement a non-monadic function that checks
whether a given value is correct and gives a proper error message
otherwise ? What is the recommended option ?

* Either String a

Preferred, usually, since Nothing is regarded as an error condition of sorts: the Monad instance for Maybe associates Nothing with `fail`, which is invoked on failed pattern matches; likewise it's mzero for MonadPlus and mempty for Monoid, both of which use it (differently) to reflect certain "failure" scenarios).

If nothing else, it would be highly confusing to see Nothing associated with success given its widespread association with failure.

Alternatively, have you considered using your own ADT? `data Validity = Success | Failure String` would give you more readable / comprehensible code without needing to worry about assumptions or common usage.

--
brandon s allbery kf8nh                               sine nomine associates
[hidden email]                                  [hidden email]
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Errors in non-monadic code

Jose A. Lopes
In reply to this post by Daniil Frumin
Yeah, non-monadic is not the best term... The problem is that it's
always so hard to communicate when you want to say a total function
that is not in the context of the IO monad. There should be a simple,
short name for these functions, so we can easily talk about them.

What ends up happening a lot of the times is that people on the
mailing list call these "pure" functions, and immediately they get an
email saying that Haskell is pure, so everything is a pure
function. In the end, it doesn't really help...

Jose

On Mon, Aug 19, 2013 at 10:09:13PM +0400, Daniel F wrote:

> On Mon, Aug 19, 2013 at 9:48 PM, <[hidden email]> wrote:
>
> > Hi,
> >
> >
> Hello!
>
>
> > What is the proper way to implement a non-monadic function that checks
> > whether a given value is correct and gives a proper error message
> > otherwise ? What is the recommended option ?
> >
>
> I am not sure, what do you mean by non-monadic. Both (Either String) and
> Maybe are monads.
>
> You can pick up whatever option you like, depending on which option, in
> your opinion, suits you better for your specific case.
> There is also a helpful errors [1] package that provide convenient means of
> converting between the results of the two approaches.
>
> Control.Error.Util.hush :: Either a b -> Maybe b
> Control.Error.Util.note :: a -> Maybe b -> Either a b
>
>
> > * Either String a
> >
> > check val
> >   | valid val = Right val
> >   | otherwise = Left errorMsg
> >
> >
> > * Maybe String
> >
> > check val
> >   | valid val = Nothing
> >   | otherwise = Just errorMsg
> >
> >
> > Cheers,
> > Jose
> >
> > _______________________________________________
> > Haskell-Cafe mailing list
> > [hidden email]
> > http://www.haskell.org/mailman/listinfo/haskell-cafe
> >
>
> [1] http://hackage.haskell.org/package/errors
>
> --
> Sincerely yours,
> -- Daniil

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Errors in non-monadic code

Brandon Allbery
In reply to this post by Brandon Allbery
On Mon, Aug 19, 2013 at 2:09 PM, Brandon Allbery <[hidden email]> wrote:
Alternatively, have you considered using your own ADT? `data Validity = Success | Failure String` would give you more readable / comprehensible code without needing to worry about assumptions or common usage.

Or possibly Valid and Invalid as the constructors....

This also means you can easily extend it later to include multiple errors, or position information, or other annotations. You could also use it with Monoid and/or the Writer monad to track success/failure in the most appropriate way for your project, instead of being constrained to the behavior of an existing instance.

--
brandon s allbery kf8nh                               sine nomine associates
[hidden email]                                  [hidden email]
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Errors in non-monadic code

Tom Ellis
In reply to this post by Jose A. Lopes
On Mon, Aug 19, 2013 at 02:20:23PM -0400, [hidden email] wrote:
> Yeah, non-monadic is not the best term... The problem is that it's
> always so hard to communicate when you want to say a total function
> that is not in the context of the IO monad. There should be a simple,
> short name for these functions, so we can easily talk about them.

Why, what would be different in your question for a non-total function or
one in the context of the IO monad?

Tom

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Errors in non-monadic code

Jose A. Lopes
I'd say that if you were in the context of the IO monad, maybe you'd
prefer to use exceptions instead of 'Either' or 'Maybe'.

Jose

On Mon, Aug 19, 2013 at 07:41:48PM +0100, Tom Ellis wrote:

> On Mon, Aug 19, 2013 at 02:20:23PM -0400, [hidden email] wrote:
> > Yeah, non-monadic is not the best term... The problem is that it's
> > always so hard to communicate when you want to say a total function
> > that is not in the context of the IO monad. There should be a simple,
> > short name for these functions, so we can easily talk about them.
>
> Why, what would be different in your question for a non-total function or
> one in the context of the IO monad?
>
> Tom
>
> _______________________________________________
> Haskell-Cafe mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/haskell-cafe

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Errors in non-monadic code

Brandon Allbery
On Mon, Aug 19, 2013 at 2:59 PM, <[hidden email]> wrote:
I'd say that if you were in the context of the IO monad, maybe you'd
prefer to use exceptions instead of 'Either' or 'Maybe'.

Even in IO, exceptions should be reserved for truly exceptional conditions (of the "program cannot safely continue" variety), not merely for error checking when this can be described as a normal flow of evaluation. Exceptions are not simply alternative flow of control, even in procedural languages; they are *disruptions* of flow of control.

--
brandon s allbery kf8nh                               sine nomine associates
[hidden email]                                  [hidden email]
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Errors in non-monadic code

Tobias Dammers

Except that people generally don't seem to agree what constitutes 'exceptional', even when disregarding the python world...

On Aug 19, 2013 9:24 PM, "Brandon Allbery" <[hidden email]> wrote:
On Mon, Aug 19, 2013 at 2:59 PM, <[hidden email]> wrote:
I'd say that if you were in the context of the IO monad, maybe you'd
prefer to use exceptions instead of 'Either' or 'Maybe'.

Even in IO, exceptions should be reserved for truly exceptional conditions (of the "program cannot safely continue" variety), not merely for error checking when this can be described as a normal flow of evaluation. Exceptions are not simply alternative flow of control, even in procedural languages; they are *disruptions* of flow of control.

--
brandon s allbery kf8nh                               sine nomine associates
[hidden email]                                  [hidden email]
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Errors in non-monadic code

Donn Cave-4
In reply to this post by Jose A. Lopes
[hidden email],
MIME-Version: 1.0
Content-type: text/plain; charset=UTF-8
In-Reply-To: <CAKFCL4VfY-Dz3Xo9ZUZ_SmfRQ2nLGDLbovU=[hidden email]>
References: <CAKFCL4VfY-Dz3Xo9ZUZ_SmfRQ2nLGDLbovU=[hidden email]>

quoth Brandon Allbery,

> Even in IO, exceptions should be reserved for truly exceptional conditions
> (of the "program cannot safely continue" variety), not merely for error
> checking when this can be described as a normal flow of evaluation.
> Exceptions are not simply alternative flow of control, even in procedural
> languages; they are *disruptions* of flow of control.

I think that would be debatable, especially as applied to procedural languages
in general.  It's very common to use exceptions in routine flow of control in
Python programs, if I remember right.  Meanwhile, the Haskell library in my
opinion somewhat weakens your case by making ordinary conditions into exceptions,
for example end-of-file.  

In the end it's a large grey area.  Ideally, what the program has to do, or
whether it can even continue at all, is determined by the program using
information reported by the function that encounters the error.  If there's
a good reason why exceptions should be used only when the program won't be
able to continue, it must be that the language's exception handling facililty
isn't very robust.

        Donn

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Errors in non-monadic code

Jose A. Lopes
I agree that whether to use exceptions or not is a very debatable
subject and it is a grey area.

Still, in your Python example, I would like to point out that just
because something is common, it does not mean it is the right thing to
do.  For example, something that some Java programmers were doing a
lot was to loop through an array and, instead of using a counter, they
were catching the array out of bounds exception. This is clearly not
the right thing to do!

But I would like to see more code move away from exceptions and into
types like "Maybe" or "Either" or other types defined for the
particular situation (as some people were suggesting in the beginning
of the thread). And the reason for this it is because when you program
against types you have to make a decision whether to handle the error
or let it bleed through: you can't ignore the choice because you can't
ignore the type. On the other hand, with exceptions, you can easily
forget to handle the exception if you're not looking at the
documentation at the time when you write the code.

Jose

On Mon, Aug 19, 2013 at 01:12:13PM -0700, Donn Cave wrote:

> [hidden email],
> MIME-Version: 1.0
> Content-type: text/plain; charset=UTF-8
> In-Reply-To: <CAKFCL4VfY-Dz3Xo9ZUZ_SmfRQ2nLGDLbovU=[hidden email]>
> References: <CAKFCL4VfY-Dz3Xo9ZUZ_SmfRQ2nLGDLbovU=[hidden email]>
>
> quoth Brandon Allbery,
>
> > Even in IO, exceptions should be reserved for truly exceptional conditions
> > (of the "program cannot safely continue" variety), not merely for error
> > checking when this can be described as a normal flow of evaluation.
> > Exceptions are not simply alternative flow of control, even in procedural
> > languages; they are *disruptions* of flow of control.
>
> I think that would be debatable, especially as applied to procedural languages
> in general.  It's very common to use exceptions in routine flow of control in
> Python programs, if I remember right.  Meanwhile, the Haskell library in my
> opinion somewhat weakens your case by making ordinary conditions into exceptions,
> for example end-of-file.  
>
> In the end it's a large grey area.  Ideally, what the program has to do, or
> whether it can even continue at all, is determined by the program using
> information reported by the function that encounters the error.  If there's
> a good reason why exceptions should be used only when the program won't be
> able to continue, it must be that the language's exception handling facililty
> isn't very robust.
>
> Donn
>
> _______________________________________________
> Haskell-Cafe mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/haskell-cafe

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Errors in non-monadic code

Tom Ellis
On Mon, Aug 19, 2013 at 05:15:39PM -0400, [hidden email] wrote:
> But I would like to see more code move away from exceptions and into
> types like "Maybe" or "Either" or other types defined for the
> particular situation (as some people were suggesting in the beginning
> of the thread). And the reason for this it is because when you program
> against types you have to make a decision whether to handle the error
> or let it bleed through: you can't ignore the choice because you can't
> ignore the type. On the other hand, with exceptions, you can easily
> forget to handle the exception if you're not looking at the
> documentation at the time when you write the code.

This is /exactly/ the reason to avoid exceptions where possible.

Tom

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Errors in non-monadic code

Patrick Mylund Nielsen
On Mon, Aug 19, 2013 at 5:24 PM, Tom Ellis <[hidden email]> wrote:
On Mon, Aug 19, 2013 at 05:15:39PM -0400, [hidden email] wrote:
> But I would like to see more code move away from exceptions and into
> types like "Maybe" or "Either" or other types defined for the
> particular situation (as some people were suggesting in the beginning
> of the thread). And the reason for this it is because when you program
> against types you have to make a decision whether to handle the error
> or let it bleed through: you can't ignore the choice because you can't
> ignore the type. On the other hand, with exceptions, you can easily
> forget to handle the exception if you're not looking at the
> documentation at the time when you write the code.

This is /exactly/ the reason to avoid exceptions where possible.

Tom


And tangentially related, it's why Go uses error return values (with functions being able to "return multiple values"), e.g. http://blog.golang.org/error-handling-and-go

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Errors in non-monadic code

Jerzy Karczmarczuk
In reply to this post by Jose A. Lopes
I would like to see more code move away from exceptions and into
types like "Maybe" or "Either" or other types defined for the
particular situation (as some people were suggesting in the beginning
of the thread). And the reason for this it is because when you program
against types you have to make a decision whether to handle the error
or let it bleed through: you can't ignore the choice because you can't
ignore the type. On the other hand, with exceptions, you can easily
forget to handle the exception if you're not looking at the
documentation at the time when you write the code.

Tom Ellis:

This is /exactly/ the reason to avoid exceptions where possible.

I disagree.

Types which neutralize some particular conditions (whether you call them exceptional or not is conventional) and propagate "Nothing" etc. is not a panacea.
Some exceptions, e.g. in the traversal of deep structures may be and ARE used as escaping continuations. Calling all that "not the right thing to do", or issuing other normative statements is, how would I express it... , is not the right thing to do. Now you can add here some dozen smileys...

More seriously, some people like exquisite continuations and will use them. Instead of fighting against exceptions it might be more fruitful to make them more robust, powerful, parametrable and sexy.


Jerzy Karczmarczuk


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Errors in non-monadic code

Jose A. Lopes
> Some exceptions, e.g. in the traversal of deep structures may be and
> ARE used as escaping continuations.

If I understand correctly, by "escaping continuations" you mean that
you can easily transfer control between the point where the exception
is raised and the exception handler.

If this is what you mean, you can achieve the same effect with monadic
code by chaining monads together, for example, you can have your
structure traversal code as several 'Maybe' functions.

And if I understand correctly the underlying technical details of
Haskell, because of continuation-passing style, the "control transfer"
should be simpler because it comes down to invoking the proper
continuation, so all of that code that compilers have to generate to
look into the stack and find the proper exception handler, and unwind
the stack and transfer control, is avoided.

Jose

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Errors in non-monadic code

Jerzy Karczmarczuk
Le 20/08/2013 00:19, [hidden email] a écrit :
> If I understand correctly, by "escaping continuations" you mean that
> you can easily transfer control between the point where the exception
> is raised and the exception handler.
>
> If this is what you mean, you can achieve the same effect with monadic
> code by chaining monads together

Yes.

José, this is mainly the question of efficiency. You don't need to
establish contact between the distant stack frames, and you may
propagate failures if this happens seldom. But if the escaping
continuation is a frequent case, it might be more economic to "jump".
This is as simple as that.

Jerzy Karczmarczuk


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Errors in non-monadic code

Tom Ellis
On Tue, Aug 20, 2013 at 12:25:44AM +0200, Jerzy Karczmarczuk wrote:

> Le 20/08/2013 00:19, [hidden email] a écrit :
> >If I understand correctly, by "escaping continuations" you mean that
> >you can easily transfer control between the point where the exception
> >is raised and the exception handler.
> >
> >If this is what you mean, you can achieve the same effect with monadic
> >code by chaining monads together
>
> José, this is mainly the question of efficiency. You don't need to
> establish contact between the distant stack frames, and you may
> propagate failures if this happens seldom. But if the escaping
> continuation is a frequent case, it might be more economic to
> "jump". This is as simple as that.

That's all very well, in which case I wish implementors of such code would
wrap their possibly-exception-throwing values in a

    newtype ThisMightThrowAnException a = ThisMightThrowAnException a

monad.  Then at least we'd all know.

Tom

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe