Reputation: 5037
I have the following instances:
instance (Typeable crypto, ToCBOR (SIPHash crypto)) => ToCBOR (SIP crypto) where
-- ...
instance (Typeable crypto, ToCBOR (Hash crypto SIPData)) =>ToCBOR (SIPHash crypto) where
-- ...
Which give rise to the following error:
• The constraint ‘ToCBOR (SIPHash crypto)’
matches an instance declaration
instance (Typeable crypto, ToCBOR (Hash crypto SIPData)) =>
ToCBOR (SIPHash crypto)
-- Defined at src/Cardano/Ledger/Spec/STS/Update/Data.hs:383:10
This makes type inference for inner bindings fragile;
either use MonoLocalBinds, or simplify it using the instance
• In the context: (Typeable crypto, ToCBOR (SIPHash crypto))
While checking an instance declaration
In the instance declaration for ‘ToCBOR (SIP crypto)’
Why do I get this error, and what is this "match" the compiler error is referring to? (as far as I can see the constraints are different).
PS: I also tried removing the Typeable crypto
constraint without any luck, I guess this is due to the compiler not looking at the LHS of the instance declaration.
Upvotes: 4
Views: 461
Reputation: 2044
Essentially, Haskell is telling you that, as written, these instances will make certain kinds of type inference that you might normally expect to work impossible. The MonoLocalBinds
language extension changes the way that the type system deals with these scenarios, so enabling it will allow your instances to function as written, but may change the semantics of your code.
Haskell normally uses the most general (most polymorphic) interpretation of a variable bound by let
or where
, but if you allow these sorts of instances, there may be multiple different, yet equally general, interpretations. MonoLocalBinds
will cause the parser to use a less general interpretation, instead of grinding to a halt or making an arbitrary decision. There's an 80-page paper from Vytiniotis, et al that explains this issue more fully, though admittedly, I don't have time to sit down and read it.
As @chi points out, GHC is letting you know that you can avoid this problem altogether (in this case) by replacing your first instance with:
instance (Typeable crypto, ToCBOR (Hash crypto SIPData)) => ToCBOR (SIP crypto)
Upvotes: 3