Track Exceptions

Hi everyone, It's always very annoying not knowing what could go wrong (what exceptions might be thrown) when calling a library function. In java doc, for instance, you can usually see what exceptions can be thrown by a specific function. I was wondering if this could be achieved for haskell by tracing "throw" and "catch" calls. Silvio

In theory, yes, but the situation becomes more complicated for
higher-order languages such as Haskell than it is for first-order(ish)
languages such as Java.*
1) Consider the higher-order function 'map'. With tracked exceptions
you would probably want to give it a type such as:
map :: forall a b e. (a -> b throws e) -> [a] -> [b] throws e
I.e., you need some kind of exception polymorphism, or severely
restrict the kind of functions you would be allowed to pass to map
(basically those that are guaranteed to not raise any exceptions).
2) One of the most commonly encountered run-time exception in Haskell
is a pattern-match failure. Whether or not these are triggered depends
not only on the control flow within your program, but also on the data
flow, making them harder to track.
Some relevant references would be:
- Kevin Glynn, Peter J. Stuckey, Martin Sulzmann & Harald Søndergaard.
"Exception analysis for non-strict languages". ICFP '02.
http://dl.acm.org/citation.cfm?id=581488
- Ruud Koot & Jurriaan Hage. "Type-based exception analysis for
higher-order non-strict languages with imprecise exception semantics".
Submitted to ICFP '14.
http://www.staff.science.uu.nl/~0422819/tbea/icfp14.pdf
Ruud
* Technically, object-oriented languages are also higher-order
languages and one can find examples where the lack of exception
polymorphism can cause trouble for Java's tracked exception mechanism.
On Thu, Mar 13, 2014 at 5:15 PM, Silvio Frischknecht
Hi everyone,
It's always very annoying not knowing what could go wrong (what exceptions might be thrown) when calling a library function. In java doc, for instance, you can usually see what exceptions can be thrown by a specific function. I was wondering if this could be achieved for haskell by tracing "throw" and "catch" calls.
Silvio _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

* Ruud Koot
1) Consider the higher-order function 'map'. With tracked exceptions you would probably want to give it a type such as:
map :: forall a b e. (a -> b throws e) -> [a] -> [b] throws e
I.e., you need some kind of exception polymorphism, or severely restrict the kind of functions you would be allowed to pass to map (basically those that are guaranteed to not raise any exceptions).
Simply instantiating b with b `Throws` e gives map :: (a -> b `Throws` e) -> [a] -> [b `Throws` e] Which is actually a more useful type than the one you proposed, because it shows that map itself doesn't throw exceptions (so that e.g. computing length is safe). Assuming "Throws e" is a monad, you could use mapM instead of map to get the behavior you want. In fact, Throws will probably need to be an indexed monad. Roman

On Thu, Mar 13, 2014 at 5:54 PM, Roman Cheplyaka
Simply instantiating b with b `Throws` e gives
map :: (a -> b `Throws` e) -> [a] -> [b `Throws` e]
Which is actually a more useful type than the one you proposed, because it shows that map itself doesn't throw exceptions (so that e.g. computing length is safe).
Assuming "Throws e" is a monad, you could use mapM instead of map to get the behavior you want.
In fact, Throws will probably need to be an indexed monad.
Roman
Yes, lazyness complicates things even further. You can pass a function to map that produces an "exception value" of type b. These exceptions would be attached to the elements inside the list [b] as you suggest. But there might also be exceptional values hidden inside the spine of the second argument of type [a]. These would need to end up in the spine of the resulting list of type [b]. Ruud

Well, Ghc 7.10 is planned to have Stack Traces, which should be exposed as
part of the Exceptions data model once that gets added,
I believe that will help quite a bit!
-Carter
On Thu, Mar 13, 2014 at 1:09 PM, Ruud Koot
Simply instantiating b with b `Throws` e gives
map :: (a -> b `Throws` e) -> [a] -> [b `Throws` e]
Which is actually a more useful type than the one you proposed, because it shows that map itself doesn't throw exceptions (so that e.g. computing length is safe).
Assuming "Throws e" is a monad, you could use mapM instead of map to get
On Thu, Mar 13, 2014 at 5:54 PM, Roman Cheplyaka
wrote: the behavior you want.
In fact, Throws will probably need to be an indexed monad.
Roman
Yes, lazyness complicates things even further. You can pass a function to map that produces an "exception value" of type b. These exceptions would be attached to the elements inside the list [b] as you suggest. But there might also be exceptional values hidden inside the spine of the second argument of type [a]. These would need to end up in the spine of the resulting list of type [b].
Ruud _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Thu, 13 Mar 2014, Ruud Koot
In theory, yes, but the situation becomes more complicated for higher-order languages such as Haskell than it is for first-order(ish) languages such as Java.*
1) Consider the higher-order function 'map'. With tracked exceptions you would probably want to give it a type such as:
map :: forall a b e. (a -> b throws e) -> [a] -> [b] throws e
Perhaps one should have a functor going from the category of badly instrumented source code to the category of instrumented source code. Or perhaps to the category of instrumented run time instances. oo--JS.
I.e., you need some kind of exception polymorphism, or severely restrict the kind of functions you would be allowed to pass to map (basically those that are guaranteed to not raise any exceptions).
2) One of the most commonly encountered run-time exception in Haskell is a pattern-match failure. Whether or not these are triggered depends not only on the control flow within your program, but also on the data flow, making them harder to track.
Some relevant references would be:
- Kevin Glynn, Peter J. Stuckey, Martin Sulzmann & Harald S�ndergaard. "Exception analysis for non-strict languages". ICFP '02. http://dl.acm.org/citation.cfm?id=581488 - Ruud Koot & Jurriaan Hage. "Type-based exception analysis for higher-order non-strict languages with imprecise exception semantics". Submitted to ICFP '14. http://www.staff.science.uu.nl/~0422819/tbea/icfp14.pdf
Ruud
* Technically, object-oriented languages are also higher-order languages and one can find examples where the lack of exception polymorphism can cause trouble for Java's tracked exception mechanism.
On Thu, Mar 13, 2014 at 5:15 PM, Silvio Frischknecht
wrote: Hi everyone,
It's always very annoying not knowing what could go wrong (what exceptions might be thrown) when calling a library function. In java doc, for instance, you can usually see what exceptions can be thrown by a specific function. I was wondering if this could be achieved for haskell by tracing "throw" and "catch" calls.
Silvio _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Hi, Ruud Koot wrote:
1) Consider the higher-order function 'map'. With tracked exceptions you would probably want to give it a type such as:
map :: forall a b e. (a -> b throws e) -> [a] -> [b] throws e
To account for exceptions hidden in thunks, I would have expected something more like this: map :: forall a b e1 e2 e3 e4 . (forall e . a throws e -> b throws e1 e) throws e2 -> [a throws e3] throws e4 -> [b throws (e1 e3, e2)] throws e4 map f [] = [] map f (x :: xs) = f x :: map f xs Note that e1 is of kind "exception -> exception". If it is a constant function, f does not force its argument; if it is the identity function, f forces its argument but cannot throw any other exceptions; etc. Interestingly, exception tracking seems to feel like strictness analysis. Tillmann

If you want to read the literature on this topic, here's a place to start: http://homepages.inf.ed.ac.uk/wadler/topics/blame.html -- Dan Burton On Thu, Mar 13, 2014 at 9:15 AM, Silvio Frischknecht < silvio.frischi@gmail.com> wrote:
Hi everyone,
It's always very annoying not knowing what could go wrong (what exceptions might be thrown) when calling a library function. In java doc, for instance, you can usually see what exceptions can be thrown by a specific function. I was wondering if this could be achieved for haskell by tracing "throw" and "catch" calls.
Silvio _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
participants (7)
-
Carter Schonwald
-
Dan Burton
-
Jay Sulzberger
-
Roman Cheplyaka
-
Ruud Koot
-
Silvio Frischknecht
-
Tillmann Rendel