error-messages
error-messages copied to clipboard
Bad error message on malformed class method type signature
Recently, Luke McCartney on discourse was confused by a bad error message. He wrote this code:
import Prelude hiding (map, Maybe, Nothing, Just, (<*>), liftA2)
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: liftA2 id
liftA2 :: (a -> b -> c) -> f a -> f b -> f c
liftA2 f x = (<*>) (fmap f x)
(*>) :: f a -> f b -> f b
a *> a2 = (id <$ a1) <*> a2
(<*) :: f a -> f b -> f a
(<*) = liftA2 const
Which produces the following error message:
Test.hs:5:5: error: [GHC-39999]
* Could not deduce `Main.Applicative f0'
from the context: Main.Applicative f
bound by the type signature for:
(<*>) :: forall (f :: * -> *) {k} (liftA2 :: k -> *) (id :: k).
Main.Applicative f =>
liftA2 id
at Test.hs:5:5-22
The type variable `f0' is ambiguous
* In the ambiguity check for `<*>'
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
When checking the class method:
(<*>) :: forall (f :: * -> *) {k} (liftA2 :: k -> *) (id :: k).
Main.Applicative f =>
liftA2 id
In the class declaration for `Main.Applicative'
|
5 | (<*>) :: liftA2 id
| ^^^^^^^^^^^^^^^^^^
This error message mentions a type signature that the user hasn't written and that cannot be found in the source file. The error message is leaking internal information from the compiler. Instead, the error message should mention the user-facing rule for type class methods, quoting the report: "The type of the top-level class method v_i
is: v_i :: ∀u,w. (C u,cx_i) ⇒ t_i
The t_i
must mention u
". I'd suggest a slightly nicer specialized message like: "The type of the class method (<*>)
should mention f
, but it is liftA2 id
".
It would also be nice if the GHC could see that liftA2 id
is a valid term and warn the user about that, but that seems more difficult.