I understand that Foo not injective, but from my analysis GHC never asked to come up with t from Foo t .
So, you are aware of the ambiguity. Let make explicitly:
type instance Foo () = Bool type instance Foo Char = Bool instance Bar () where -- I omit the declaration for f g = True instance Bar Char where g = False main = print (g :: Bool)
Your problem with f = Foobar g is ambiguity.
The bottom line: the definition of f = Foobar g does not mean that g can be selected in the same instance as f . This may apply to another instance!
Consider
show (x,y) = "(" ++ show x ++ ", " ++ show y ++ ")"
Above, RHS uses show from another instance of where LHS show .
On your line f = Foobar g GHC reports that g :: Foo t , where t is the same index of the instance of f . However, this is not enough to select an instance for g ! In fact, we could have Foo t ~ Foo t0 for some other t0 , so g can refer to g in instance t0 , causing an ambiguity error.
Note that your code is rejected by GHC 8, even if the last line is commented out, because type g is inherently ambiguous:
• Couldn't match expected type 'Foo t' with actual type 'Foo t0' NB: 'Foo' is a type function, and may not be injective The type variable 't0' is ambiguous • In the ambiguity check for 'g' To defer the ambiguity check to use sites, enable AllowAmbiguousTypes When checking the class method: g :: forall t. Bar t => Foo t In the class declaration for 'Bar'
We can follow the suggestion to make GHC 8 softer, for example GHC 7. This will do a code check of your code until we uncomment the last line.
• Couldn't match expected type 'Foo t' with actual type 'Foo t0' NB: 'Foo' is a type function, and may not be injective The type variable 't0' is ambiguous
This is the same error as in GHC 7. In GHC 8, we have another luxury: we can explicitly choose t for g as follows:
class Bar t where f :: Foobar t f = Foobar (g @ t) g :: Foo t
This requires, of course, a few more extensions. In GHC 7, you need a proxy server to be able to select an instance uniquely.