2

Here I have a little bit of code that seems to implement a "purely" functional version of try-catch: Evaluate a value, and if an error occurs, return a different given value of the same type. The example below works in GHCi.

The first argument to pureCatch is the value to attempt to compute. The second argument is the value to use if an exception occurs while calculating it. (Could obviously be replaced with the use of Maybe, but the effect is the same.)

:set -XScopedTypeVariables
import System.IO.Unsafe
import Control.Exception

let pureCatch :: a -> a -> a; pureCatch (value :: x) if_err = unsafePerformIO (catch (evaluate (value)) ((\_ -> (return if_err)) :: (SomeException -> IO x)) )


>pureCatch (head [1]) 2
1

>pureCatch (head []) 2
2

>pureCatch (["value"] !! 0) "error"
"value"

>pureCatch ([] !! 0) "error"
"error"

Are there any errors that cannot be caught using this technique, apart from serious system errors like out of memory or GHC bugs or something? Could this function be extended to catch any other types of errors?

Is the use of unsafePerformIO really unsafe here? How? Could this crash the program completely?

Is this technique guaranteed to catch all exceptions in the evaluation of "value"?

Is there anything non deterministic about this technique, or undefined behavior from the perspective of the Haskell language?

Anything else I should know about this? (Tell me how naughty I am for attempting to catch everything :) ) I'm not necessarily going to use this anywhere, this is intellectual curiosity. I'm not a Haskell programmer.

Can it be written with nicer syntax or not require XScopedTypeVariables?

I get the feeling that this is probably the function that beginning Haskell programmers would love to use to catch errors. So, why not?

  • I marked this as a duplicate of the spoon question because this question essentially reimplements spoon – luqui Dec 28 '16 at 08:20
  • 2
    In short, it allows to define non-monotonic functions on domains. This is unlike everything else, so it can be surprising. Also, one should be very careful about when errors are generated. E.g. in `pureCatch ([[undefined]] !! 0) [4]` one could easily think the result will be completely bottom-free, when this is not the case. – chi Dec 28 '16 at 10:32

0 Answers0