Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell "exceptions"

I've got a set of users, groups, and a mapping between users and groups. I have various functions that manipulate these sets, however one should not be able to add a user<->group mapping for a user that does not exist, nor remove a group which still has users as members, etc.

So basically I want these functions to throw "exceptions" that must be explicitly dealt with by the caller.

I first thought of returning something like this:

data Return r e = Success r | Exception e

And if the caller fails to pattern match against the Exception, they'll hopefully get a compiler warning, or at the very least have an obvious runtime error when there is a problem.

Is this the best approach, and is there a pre-packaged solution that does this? Note I need to throw and catch "exceptions" in pure code, not the IO Monad.

like image 554
Clinton Avatar asked May 16 '12 02:05

Clinton


People also ask

Does Haskell have exception handling?

The Haskell runtime system allows any IO action to throw runtime exceptions. Many common library functions throw runtime exceptions. There is no indication at the type level if something throws an exception. You should assume that, unless explicitly documented otherwise, all actions may throw an exception.

How do you use either in Haskell?

In Haskell either is used to represent the possibility of two values. Either is used to represent two values that can be correct or error. It has two constructors also which are named Left and Right. These constructors also represent and show some purpose either in Haskell.

What is error Haskell?

On the one hand, an error is a programming mistake such as a division by zero, the head of an empty list, or a negative index. If we identify an error, we remove it. Thus, we don't handle errors, we simply fix them. In Haskell, we have error and undefined to cause such errors and terminate execution of the program.

What is an exception in java?

Definition: An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program's instructions. When an error occurs within a method, the method creates an object and hands it off to the runtime system.


2 Answers

Yes, this is a good approach, and it's in the standard library: Return r e is the same as Either e r. You can even write code like you would using exceptions in IO, too (i.e. without having to explicitly handle the errors at each step with pattern matching): the Monad instance for Either propagates the errors, just like the Maybe monad does (but with the additional e value in the case of an error). For example:

data MyError
    = Oops String
    | VeryBadError Int Int

mightFail :: T -> Either MyError Int
mightFail a = ...

foo :: T -> T -> Int -> Either MyError Int
foo a b c = do
    x <- mightFail a
    y <- mightFail b
    if x == y
        then throwError (VeryBadError x y)
        else return (x + y + c)

If mightFail a or mightFail b returns Left someError, then foo a b c will, too; the errors are automatically propagated. (Here, throwError is just a nice way of writing Left, using the functions from Control.Monad.Error; there's also catchError to catch these exceptions.)

like image 198
ehird Avatar answered Sep 23 '22 15:09

ehird


The Return r e type that you are describing is exactly the standard type

data Either a b = Left a | Right b

You might want to use the so called "error monad" (a more suitable name is "exception monad") of the mtl package. (Alternatively, there's ExceptionT in the monadLib package if you don't want to use mtl.) This allows you to do error handling in pure code by invoking throwError and catchError. Here you can find an example that shows how to use it.

like image 20
Peter Avatar answered Sep 21 '22 15:09

Peter