Search code examples
haskellmonads

Haskell fails to infer the return type of a monad after using the sequence operator


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 ?


Solution

  • 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