Skip to content

Unclear error message for ambigous instance when instance type does not occur in any function argument.

Consider a definition like this:

{-# LANGUAGE ScopedTypeVariables #-}
mfbs :: forall a. FiniteBits a => Int
mfbs = finiteBitSize (undefined :: a)

And the resulting error message:

lib\BitFields\ObjFields.hs:14:9: error:
    * Could not deduce (FiniteBits a0)
      from the context: FiniteBits a
        bound by the type signature for:
                   mfbs :: forall a. FiniteBits a => Int
        at lib\BitFields\ObjFields.hs:14:9-37
      The type variable `a0' is ambiguous
      Potentially matching instances:
        instance FiniteBits a => FiniteBits (And a)
          -- Defined in `Data.Bits'
        instance FiniteBits a => FiniteBits (Iff a)
          -- Defined in `Data.Bits'
        ...plus five others
        (use -fprint-potential-instances to see them all)
    * In the ambiguity check for `mfbs'
      To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
      In the type signature: mfbs :: forall a. FiniteBits a => Int
   |
14 | mfbs :: forall a. FiniteBits a => Int
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

This makes sense. At a call site to mfbs there is "obviously" no way to tell the compiler which instance to use.

But I found the error message here very unhelpful if not harmful. It says Could not deduce (FiniteBits a0) from the context: FiniteBits a. Why does it refer to a0 when there should be only one a given the use of scoped type variables? I assume this is the fallout of an implementation detail in the ambiguity check.

Maybe for a function with a type like f :: (C a,...) => ... we could check if a occurs only in the constraints and if so give a more specific warning.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information