[Haskell] Catching error / making library functions monadic (in
Philip K.F. Hölzenspies
p.k.f.holzenspies at utwente.nl
Wed Oct 8 10:37:49 EDT 2008
I'm working on a graph generator that involves a lot of random selection out
of a list of vertices. Basically, there are functions that look a little like
select vs = randomRM (0,length vs - 1) >>= return . (vs !!)
where randomRM is a lot like Random.randomRIO, except that it is not in the IO
monad, but rather in any monad, i.e.
class Monad m => RandomM m where
randomM :: m a
randomRM :: (a,a) -> m a
instance RandomM IO where
randomM = randomIO
randomRM = randomRIO
The problem is, obviously, that when the list of vertices (vs) is
empty, "select vs" will result in an error. The Prelude defines (!!) as:
xs !! n | n < 0 = error "Prelude.!!: negative index"
 !! _ = error "Prelude.!!: index too large"
(x:_) !! 0 = x
(_:xs) !! n = xs !! (n-1)
The function 'error' is implemented (at least in GHC) using
Control.Exception.throw. Unfortunately, 'catch' does not seem to work. From
Prelude> catch (return $  !! 0) (const $ putStrLn "foo" >> return 42)
*** Exception: Prelude.(!!): index too large
Is there any way to catch errors in functions in libraries (like the Prelude)?
This is made even more necessary by the fact that the default implementation
for 'fail' in a monad is 'error'. I would already be happy if I could make
all applications of error change into applications of fail, as defined in my
monad. Preferably, though, I would not even need a failure mechanism in my
own monad, but rather have an ErrorMonad (or something similar) and just have
class Monad m => ErrorMonad error m | m -> error where
onError :: m a -> (error -> a) -> a
For now, I simply reimplement the functions I need that give errors.
More information about the Haskell