4

(Apologies if my terminology is wrong).

I'm trying to write a wrapper function that handles exceptions: if the given IO action throws, it returns Nothing (inside an IO context of course), but if the given IO action succeeds, it returns Just v.

tryMaybe :: IO a -> IO (Maybe a)
tryMaybe action = do
    result <- (try action) :: IO (Either SomeException a)
    return $ case result of
        Left _  -> Nothing
        Right v -> Just v

This results in the compiler error message:

  Couldn't match type `a' with `a1'
      `a' is a rigid type variable bound by
          the type signature for tryMaybe :: IO a -> IO (Maybe a)
          at src/Database.hs:33:13
      `a1' is a rigid type variable bound by
           an expression type signature: IO (Either SomeException a1)
           at src/Database.hs:35:15
    Expected type: IO a1
      Actual type: IO a
    In the first argument of `try', namely `action'

I'm guessing that the type variable a in the first line isn't the same as the a in the third line - they just happen to have the same name in the source code, and the compiler has renamed it a1 in the error message.

So how do I tell Haskell that these are the same types?

stusmith
  • 14,003
  • 7
  • 56
  • 89

1 Answers1

10

You need to enable the ScopedTypeVariables extension, and the change the type signature of the top-level function to start with forall a .:

{-# LANGUAGE ScopedTypeVariables #-}

...

tryMaybe :: forall a . IO a -> IO (Maybe a)
...

The forall syntax brings the type variable a into scope for the entire body of tryMaybe, rather than it being limited to the type signature which is the default. This is mainly a historical anomaly rather than a deliberate design.

Ganesh Sittampalam
  • 28,821
  • 4
  • 79
  • 98
  • 6
    Aha yes that sorted it. I understand that GHC is trying to maintain backwards compatibility with Haskell 98 here, but I would have thought a warning about type variable shadowing (if that's the right term), plus a hint to investigate that language extension, might be helpful to newbies like me. Ah well I live and learn. Many thanks! – stusmith Jun 24 '14 at 20:54
  • 5
    @stusmith I think a shadow warning is a great idea. You should file a ghc enhancement ticket. – augustss Jun 24 '14 at 21:17