Catching Exceptions in Haskell

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

Catching Exceptions in Haskell

Bjoern Brandenburg
Hi all,

I'm struggling to figure out how to catch an exception in Haskell.

Eventually, what I want to do is to use the Control.Macho library
(from Hackage) to parse binaries on Mac OS X. Naturally, I would like
my program to gracefully handle corrupted files or files that aren't
binaries. So I need to catch exceptions if the parsing with Data.Macho
fails...

This is what I've got so far:
http://hpaste.org/fastcgi/hpaste.fcgi/view?id=1877#a1877

Digression: Note that if I leave out the `foo e` call, then I get

scratch.hs:21:9:
    Ambiguous type variable `e' in the constraint:
      `Exception e' arising from a use of `try' at scratch.hs:21:9-11
    Probable fix: add a type signature that fixes these type variable(s)

I find this somewhat counter-intuitive; this is also not discussed in
the book "Real-World Haskell" (at least I haven't found it), which is
what I'm using to learn Haskell. What is the best way to get around
this?

Back to my problem. The program produces the following output:

$ runghc scratch.hs
Testing Pure... Caught a bad exception: abort via error
Testing Macho... No exception occured, the result is:
scratch.hs: too few bytes. Failed reading at byte position 4

This counter-intuitive in at least two ways:

1) How can it fail at position 4 in an empty string? That looks like a
sloppy error message too me; why doesn't it report the actually
failing position?

2) Why can I catch an exception raised with an error in my own code,
but not the one raised by Data.Binary.Get? Looking at
http://hackage.haskell.org/packages/archive/binary/0.5/doc/html/src/Data-Binary-Get.html#failDesc
, an exception within Data.Binary.Get is also raised with error. What
is the difference?

Why am I seeing what I'm seeing, and how should I be doing it in the
first place?

Thanks in advance,
Bjoern
Reply | Threaded
Open this post in threaded view
|

Re: Catching Exceptions in Haskell

Bjoern Brandenburg
Ok, so I was able to extract a simpler program with the same symptoms.

http://hpaste.org/fastcgi/hpaste.fcgi/view?id=1900#a1900

Apparently the exception is only triggered when m is used in line 31.
So I guess that evaluate in line 24 is not causing strict evaluation
of the Data.Binary.Get monad, even though it is working for the error
and assert tests.

Why is that? Is that expected? If so, what am I doing wrong?

Thanks,
Bjoern
Reply | Threaded
Open this post in threaded view
|

Re: Catching Exceptions in Haskell

Peter Verswyvelen-2
The 3rd exception is raised when (show m) is computed, since no
exception occurred when evaluating (testGet L.empty) itself.

When you call "evaluate?a", it only forces "one level" of?evaluation of a.


E.g. if you would run

> evaluate (1:error "2":[]) >>= print . head

this would print 1, and not give an error.


You can maybe understand this better when you change

> (res :: Either SomeException String) <- try $ evaluate (f x)

into

> (res :: Either SomeException String) <- try $ return (f x)

Now the 2nd exception won't be raised either: evaluate digged one
level into assert, and that causes an exception, but return will not
do that, it will just return the unevaluated thunk that wraps the
assert computation, and this thunk will get evaluated when you print
it

You can get the behavior what you expect by using some functions from
Control.Parallel.Strategies.

Change

(res :: Either SomeException String) <- try $ evaluate (f x)

into

(res :: Either SomeException String) <- try $?evaluate?(f x `using` rnf)


Now all 3 will throw an exception, as you expected.?Why? (a `using`
rnf) reduces its argument (a) to "head normal form", which basically
means it evaluating all sub-expressions at all levels.

So

> evaluate (1:error "2":[] `using` rnf) >>= print . head

will now give an error.

Cheers,
Peter Verswyvelen






On Sun, Mar 1, 2009 at 1:48 AM, Bjoern Brandenburg <[hidden email]> wrote:

>
> Ok, so I was able to extract a simpler program with the same symptoms.
>
> http://hpaste.org/fastcgi/hpaste.fcgi/view?id=1900#a1900
>
> Apparently the exception is only triggered when m is used in line 31.
> So I guess that evaluate in line 24 is not causing strict evaluation
> of the Data.Binary.Get monad, even though it is working for the error
> and assert tests.
>
> Why is that? Is that expected? If so, what am I doing wrong?
>
> Thanks,
> Bjoern
> _______________________________________________
> Beginners mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: Catching Exceptions in Haskell

Bjoern Brandenburg
On Sat, Feb 28, 2009 at 9:16 PM, Peter Verswyvelen <[hidden email]> wrote:
> When you call "evaluate?a", it only forces "one level" of?evaluation of a.

I missed this fact when reading the documentation about evaluate.
Thank you for your explanation.

- Bjoern