Skip to content

Quantified constraint error should show more context

Motivation

QuantifiedConstraints sometimes leads to incomplete error message for which it is rather difficult to understand / locate the source of the error.

See the following example:

{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE RankNTypes, ScopedTypeVariables, QuantifiedConstraints, TypeApplications, DataKinds, ConstraintKinds, AllowAmbiguousTypes #-}
module QC2 where

import GHC.TypeLits
import Data.Proxy

data Array (n :: Nat) = Array

class IsEqual t

instance KnownNat n => IsEqual (Array n)

blork :: forall c.
  (forall k. {- KnownNat k => -} c (Array k)) => 
  (forall k. c k => k -> Bool) -> Bool
blork f = case someNatVal 10 of
    Nothing -> False
    Just (SomeNat (_ :: Proxy n)) -> f (Array @n)

blip :: Bool
blip = blork @IsEqual (\_ -> True)

The comment around KnownNat k => can be removed to fix the following error:

QC2.hs:22:8: error:
     No instance for (KnownNat k) arising from a use of blork
      Possible fix:
        add (KnownNat k) to the context of a quantified context
     In the expression: blork @IsEqual (\ _ -> True)
      In an equation for blip: blip = blork @IsEqual (\ _ -> True)
   |
22 | blip = blork @IsEqual (\_ -> True)
   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^

This error show the call site and a "Possible fix". However it does not give any hint about the location of the erroneous quantified constraint. The developer must manually locate the blork function and, amongs the list of quantified constraints in its context, locate the erroneous one.

Note that GHC is smart enough to use the right name for the type variable k in the error message, this helps a bit. However, as depicted in my example, the constraint of blork may many quantified constraint using all the same type variable (because they are independent).

It took me a lot of time to first understand that the error was in the blork function. Now I'm used to this error, but locating the erroneous quantified constraint is still difficult.

Proposal

I'd like a more detailed error message, such as:

QC2.hs:22:8: error:
     No instance for (KnownNat k) arising from a use of blork
      Possible fix:
        add (KnownNat k) to the context of a quantified context
        in the `blork` function context:

         15  |  blork :: forall c.
             |  (forall k. c (Array k)) => 
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
     In the expression: blork @IsEqual (\ _ -> True)
        In an equation for blip: blip = blork @IsEqual (\ _ -> True)
   |
22 | blip = blork @IsEqual (\_ -> True)
   |      

I'd like something similar to the hint associated with missing constraint in this context:

foo :: t -> String
foo = show
     No instance for (Show t) arising from a use of show
      Possible fix:
        add (Show t) to the context of
          the type signature for:
            foo :: forall t. t -> String
     In the expression: show
      In an equation for foo: foo = show
Edited by Guillaume Bouchard
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information