Edit : The GHC Instance Resolution User Guide section is a good place to start.
Here's how to break down why this happens. Your z roughly equivalent to this:
z :: Bar a -> Bar Int -> E (Bar a) (Bar Int) z = (>->)
Now itβs clear why this is not possible? We get the error:
SO26146983.hs:20:5: No instance for (Foo (Bar a) (Bar Int)) arising from a use of `>->' In the expression: (>->) In an equation for `z': z = (>->)
There is nothing to see that a ~ Int . Rewrite it:
z' :: (a ~ Int) => Bar a -> Bar Int -> E (Bar a) (Bar Int) z' = (>->)
This works great even with your original copy. (Edit: I suspect the following sentence is either useless or misleading, or both.) z' (approximately), where typechecker ends with your rewritten instance definition: it sees an instance for (Bar a) (Bar a') , which requires (a ~ a') , and simply adds this constraint to the call.
Roughly speaking, the resolution of an instance goes from right to left, and sometimes unexpected consequences.
Edit: And the result of resolving from right to left is that instance (x ~ x') => Foo (Bar x) (Bar x') matches any two types x and x' , whether or not x ~ x' valid, Constraint just spreads to the call site. Therefore, you cannot write another instance for certain types. It will overlap, which is prohibited by default, and, in addition, the GHC does not specifically back out when resolving instances. instance Foo (Bar x) (Bar x) , on the other hand, will not be applied if it does not have the same type in both places - the GHC will not invent a constraint because (x ~ y) => M xy does not match with M xx .
Depending on your actual usecase, you can read the documentation for OverlappingInstances . Again, depending on what you are doing, some of the recent innovations in families , such as closed family types , may be relevant.