error-messages icon indicating copy to clipboard operation
error-messages copied to clipboard

Bad error message on malformed class method type signature

Open noughtmare opened this issue 1 year ago • 0 comments

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.

noughtmare avatar Jan 10 '24 18:01 noughtmare