How to specify the type variable used by the built-in type is the same as the type variable used in the function definition?

(Sorry if my terminology is incorrect).

I'm trying to write a wrapper function that handles exceptions: if the given action IOthrows, it returns Nothing(inside the context IO, of course), but if the given action IOis successful, 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

As a result, a compiler error message appears:

  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 assume that the type variable ain the first line does not match the athird line - they just have the same name in the source code, and the compiler has renamed it a1to an error message.

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

+4
1

ScopedTypeVariables , forall a .

{-# LANGUAGE ScopedTypeVariables #-}

...

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

forall a tryMaybe, , . , .

+10

Source: https://habr.com/ru/post/1545899/


All Articles