confusing type error

Evan Laforge qdunkan at gmail.com
Thu Dec 4 18:50:10 UTC 2014


I recently got a confusing error msg, and reduced it to a small case:

f1 :: Monad m => m Bool
f1 = f2 0 0 'a'

f2 :: Monad m => Int -> Float -> m Bool
f2 = undefined

>From this, it's clear that f2 is being given an extra Char argument it
didn't ask for.  However, the error msg (ghc 7.8.3) is:

    Couldn't match type ‘m Bool’ with ‘Bool’
    Expected type: Char -> m Bool
      Actual type: Char -> Bool
    Relevant bindings include f1 :: m Bool (bound at Bug.hs:4:1)
    The function ‘f2’ is applied to three arguments,
    but its type ‘Int -> Float -> Char -> Bool’ has only three
    In the expression: f2 0 0 'a'
    In an equation for ‘f1’: f1 = f2 0 0 'a'

The confusing part is that 'f2' was applied to three arguments, but
it's type has only three.  It includes the Char in expected and actual
types, and implies that the type of 'f2' includes the Char.  So I took
quite a while to realize that the type of 'f2' in fact *didn't* expect
a Char (and had an 'm'), so that the "but its type" is *not* in fact
its declared type.

I suppose it infers a type for 'f2' based on its use, and that then
becomes the "actual" type, but it seems less confusing if it picked
the declared type of 'f2' as its actual type.  Perhaps this is working
as intended, but it it is confusing!  Especially the part about
"expected three but got three".

Ideally I'd like to see "too many arguments" or at least "expected
(Char -> m Bool) but actually 'm Bool'".  Actually I'd expect the
other way: "expected 'm Bool' but got (Char -> m Bool)' but I think
ghc has always done it backwards from how I expect.  It looks like
it's substituting (->) for 'm', so maybe it's one of those things
where ((->) a) is also a monad.


More information about the Glasgow-haskell-users mailing list