Lets say we've got a function like f below, that returns a monad. However, where you see Int
, pretend it's a really complicated type.
f :: (Monad m) => m Int -- Pretend this isn't Int but something complicated
f = return 42
Now lets say we want to force this into the Maybe
monad. We don't need to write the full type of f
to do this, we can just do the following:
g :: Maybe a -> Maybe a
g = id
main = print $ (g f)
The dummy function g
forces f
to become Maybe
.
I think the above is rather messy. What I'd rather write is this:
main = print $ (f :: Maybe a)
But it fails with the following error:
Couldn't match expected type `a' against inferred type `Int'
`a' is a rigid type variable bound by
the polymorphic type `forall a. Maybe a' at prog.hs:7:16
Expected type: Maybe a
Inferred type: Maybe Int
In the second argument of `($)', namely `(f :: Maybe a)'
In the expression: print $ (f :: Maybe a)
Is there a way to do what g
above does in a less messy way that doesn't involve creating a new function? I don't want to write f :: Maybe Int
, as it becomes a maintenance problem if the return type changes. GHC extensions are okay in answers.
Use asTypeOf
. It returns the first argument while unifying its type with that of the second. It's just a type-restricted version of const
, but useful for situations like this.
main = print $ f `asTypeOf` (undefined :: Maybe a)
Yet another way is to restrict the type of print
:
main = (print :: Show a => Maybe a -> IO ()) f
UPDATE:
GHC 8.0.1 introduced TypeApplications extension which can be used to force Maybe
:
{-# LANGUAGE TypeApplications #-}
main = print $ f @Maybe
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With