Opened 4 years ago

Closed 4 years ago

Last modified 4 years ago

#7578 closed bug (invalid)

Instance selection regression from 7.4 to 7.6

Reported by: nomeata Owned by:
Priority: normal Milestone:
Component: Compiler (Type checker) Version: 7.6.1
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:


The following code (useless due to minification) works in GHC 7.4.1:

{-# LANGUAGE FlexibleInstances, UndecidableInstances, OverlappingInstances #-}

class CollectArgs a where
    randomEvaluate :: a -> ()

instance CollectArgs b => CollectArgs (a -> b) where
    randomEvaluate f = randomEvaluate (f undefined)
        where () = randomEvaluate (f undefined)

instance Show a => CollectArgs a where
    randomEvaluate x = ()

In 7.6.2-rc1, I get this error message

    Could not deduce (Show b) arising from a use of `randomEvaluate'
    from the context (CollectArgs b)
      bound by the instance declaration at test.hs:6:10-46
    Possible fix:
      add (Show b) to the context of the instance declaration
    In the expression: randomEvaluate (f undefined)
    In a pattern binding: () = randomEvaluate (f undefined)
    In an equation for `randomEvaluate':
        randomEvaluate f
          = randomEvaluate (f undefined)
              () = randomEvaluate (f undefined)

The error message goes away if I remove the () = randomEvaluate (f undefined) binding, i.e. the first recursive use of randomEvaluate works fine.

(This came up at

Change History (2)

comment:1 Changed 4 years ago by simonpj

difficulty: Unknown
Resolution: invalid
Status: newclosed

Currently this is by-design. What is happening is this. At the local binding of (), GHC is trying to infer the most general type of the binding. It sees a constraint (CollectArgs b) but at that moment it has a very local view, so it tries to simplify it. Aha. There is an instance declaration instance Show a => CollectArgs a which matches. Let's use that! Disaster.

You are skating on very thin ice indeed, becuase there are two ways of seeming to satisify (CollectArgs b), one from the context of the first instance decl, and one from the second instance decl itself.

The simple way to fix this is to use -XMonoLocalBinds which stops GHC trying to generalise the type of the local declatation. This is good in lots of ways: see Let should not be generalised. I'd be happy for it to be the default, and it's implied by -XGADTs and similar, but currently the default is still to generalise local bindings.


comment:2 Changed 4 years ago by nomeata

Thanks for the clear explanation. I linked it from the SE post so that it will enlighten more Haskellers.

Note: See TracTickets for help on using tickets.