The following code
import Control.Monad.Writer
class Foo c where
fromInt :: Int -> c
instance Foo [Int] where
fromInt n = [n]
instance (Monoid c, Foo c) => Foo (Writer c ()) where
fromInt d = writer ((),fromInt d)
onetwo :: Writer [Int] ()
onetwo = fromInt 1 >> fromInt 2
yields the following error :
Ambiguous type variable `a0' arising from a use of `fromInt' prevents the constraint
`(Foo (WriterT [Int] Data.Functor.Identity.Identity a0))'
from being solved.
So it looks like Haskell fails to infer the return type of the Writer monad, but I don't understand why, since it can only be the unit type based on the implementation of fromInt
.
Why does Haskell fail to infer this ?
The problem is essentially the left operand in fromInt 1 >> fromInt 2
. Indeed, (>>)
has as type (>>) :: Monad m => m a -> m b -> m b
. This means that with the type of the result, we know what m
and b
are, but not a
.
That is a problem here. Yes, we defined an instance instance Foo (Writer c ())
, and currently that is the only instance. But that does not exclude that (another) programmer could later add an instance:
instance Foo (Writer [Int] Bool)
-- …
for example, and since a
is not known, it can be anything.
We can fix this by specifying the type of the first operand, for example with:
onetwo :: Writer [Int] ()
onetwo = (fromInt 1 :: Writer [Int] ()) >> fromInt 2