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

could not deduce [instance]

Open sfultong opened this issue 2 years ago • 2 comments

• Could not deduce (PrettyPrintable a)
    arising from a use of ‘cleanA’
  from the context: (Traversable f, Show s, Show1 f, Eq s, Eq1 f,
                     PrettyPrintable1 f)
    bound by the type signature for:
               sizeTerm :: forall (f :: * -> *) s.
                           (Traversable f, Show s, Show1 f, Eq s, Eq1 f,
                            PrettyPrintable1 f) =>
                           Integer
                           -> StuckExpr (SizeStuck s) (StuckUnsizedBase f)
                           -> Either
                                UnsizedRecursionToken
                                (StuckExpr (SetStuck s) (StuckAbortBase f))
    at src/Telomare/Possible.hs:(564,1)-(565,133)
  Possible fix:
    add (PrettyPrintable a) to the context of
      a type expected by the context:
        forall a.
        Base
          (EnhancedExpr
             (SplitFunctor
                (SplitFunctor
                   (SplitFunctor (SplitFunctor f UnsizedRecursionF) AbortableF)
                   SuperPositionF)
                (StuckF
                   (SetStuck (Either s StuckNeedsSizing))
                   (StuckExpr
                      (SetStuck (Either s StuckNeedsSizing))
                      (SplitFunctor
                         (SplitFunctor (SplitFunctor f UnsizedRecursionF) AbortableF)
                         SuperPositionF)))))
          a
        -> Base
             (EnhancedExpr
                (SplitFunctor
                   (StuckAbortBase f)
                   (StuckF (SetStuck s) (StuckExpr (SetStuck s) (StuckAbortBase f)))))
             a
• In the first argument of ‘hoist’, namely ‘cleanA’
  In the expression: hoist cleanA
  In an equation for ‘clean’: clean = hoist cleanA
|
663 |   clean = hoist cleanA

This seems bad to me for at least two reasons. The first is that the type variable a is only made clear in the possible fix. The second is that the possible fix is not a fix.

Original post on reddit: https://www.reddit.com/r/haskell/comments/y40ydi/ghc_could_not_deduce_instance/

sfultong avatar Oct 14 '22 21:10 sfultong

Here's a simple standalone program that produces the same kind of error message:

{-# LANGUAGE RankNTypes #-}

f :: (forall a. a -> String) -> String
f g = g (\x -> x)

main :: IO ()
main = putStrLn $ f show

With the error message:

T.hs:6:21: error:
    • No instance for (Show a) arising from a use of ‘show’
      Possible fix:
        add (Show a) to the context of
          a type expected by the context:
            forall a. a -> String
    • In the first argument of ‘f’, namely ‘show’
      In the second argument of ‘($)’, namely ‘f show’
      In the expression: putStrLn $ f show
  |
6 | main = putStrLn $ f show
  |                     ^^^^

I agree that it would be great if the error message could mention where the type variable a comes from, so in this case it should point to the type signature of the f function.

And applying the suggested fix does not work, because the type of the function \x -> x is not an instance of Show (I chose this example intentionally for this reason). In general, I think it might be more common that this suggested fix won't work. Especially if the constraint would need to be added in another module or even another package.

So I would propose the error message to change to:

T.hs:6:21: error:
    • No instance for (Show a) arising from a use of ‘show’
         where 'a' is bound in the type signature for:
            f :: (forall a. a -> String) -> String
                         ^
  |
6 | main = putStrLn $ f show
  |                     ^^^^

And I would also change the error message for a similar error for this example:

f :: a -> String
f = show

It now gives:

T.hs:6:5: error:
    • No instance for (Show a) arising from a use of ‘show’
      Possible fix:
        add (Show a) to the context of
          the type signature for:
            f :: forall a. a -> String
    • In the expression: show
      In an equation for ‘h’: h = show
  |
6 | f = show
  |     ^^^^

I propose changing it to:

T.hs:6:5: error:
    • No instance for (Show a) arising from a use of ‘show’
         where 'a' is bound in the type signature for:
            f :: forall a. a -> String
                        ^
      Possible fix:
        add (Show a) to the type signature of 'f'
  |
6 | f = show
  |     ^^^^

Although in this case the user has not actually written forall a. so that might be confusing too.

noughtmare avatar Oct 15 '22 12:10 noughtmare

Thanks for the elaboration, @noughtmare. I also prefer your proposed error messages.

sfultong avatar Oct 15 '22 14:10 sfultong