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