5
votes

Continuing roadblocks when trying to learn Haskell.

I am following the "Real World Haskell" and when it comes to getting one of their complex examples to work, I obtain the following error

"Ambiguous type variable e' in the constraint: GHC.Exception.Exception e' arising from a use of `handle' at FoldDir.hs:88:14-61 Probable fix: add a type signature that fixes these type variable(s)"

My relevant bits of code are:

import Control.Exception (bracket, handle)
maybeIO :: IO a -> IO (Maybe a)
maybeIO act = handle (\_ -> return Nothing) (Just `liftM` act)

How do I eradicate this error?

3

3 Answers

14
votes

You need to specify a type for the handler-function's argument, so it knows which kinds of exceptions to handle.

You can either do this by naming the function

import Control.Exception (handle, SomeException)
maybeIO act = handle handler (Just `liftM` act)
    where handler :: SomeException -> IO (Maybe a)
          handler _ = return Nothing

Or by using the ScopedTypeVariables extension:

{-# LANGUAGE ScopedTypeVariables #-}
import Control.Exception (handle, SomeException)
maybeIO act = handle (\(_ :: SomeException) -> return Nothing) (Just `liftM` act)
1
votes

Control.Exception exposes a different interface in GHC 6.10 and later. For a quick fix, change

import Control.Exception (bracket, handle)

to

import Control.OldException (bracket, handle)
1
votes

Control.OldException is deprecated. With extensible exceptions, one needs to specify a type for the exception, even if it is never used. My version of maybeIO is

perhaps ∷ forall a. IO a → IO (Maybe a)
perhaps task = do
  result ← (try ∷ IO a → IO (Either IOException a)) task
  return $ either (const Nothing) Just result

One needs the explicit forall to bring the type variable a into scope, and the GHC compiler flag -XExplicitForAll to use the explicit forall. One cannot give try a type out in the open without getting the error "You cannot give a type signature for an imported value." If one tries the type declaration elsewhere, e.g. on the result of try task then GHC can't sort it out. So yes, this is a bit embarrassing for us strong typing advocates, but it gets better.