I have reduced everything to the most necessary, so bear with me if the example code below is contrived. Say we have:
class Foo a where foo :: a data Type a = Type a instance (Foo a) => Foo (Type a) where foo = Type foo
Now suppose I want to make a Type a instance, say Show , when a is an instance of both Foo and Show ( Show was chosen to avoid defining another type). So, how do we want Type a be an instance of Show ? Well, if we are not crazy, we certainly want it to be something like
instance (Foo a, Show a) => Show (Type a) where show (Type x) = show x
or maybe
instance (Foo a, Show a) => Show (Type a) where show (Type x) = "Blabla " ++ (show x)
This is all great and works great. For some inexplicable reason, we would like Show output everything that foo :: a looks / displays like! In our far-fetched setting, I canβt imagine why we want this, but let me say that we do it. In case not
instance (Foo a, Show a) => Show (Type a) where show _ = show foo
do the trick?
Alas, the GHC says
Ambiguous variable of type 'a' in Constraints: 'Foo a' [...] 'Show'
Maybe the GHC can't figure out what kind of Foo I'm talking about. I mean foo :: Type a or foo :: a ? Change the previous fragment to
instance (Foo a, Show a) => Show (Type a) where show _ = show (foo :: a)
gives me
Failed to deduce (Foo a1) from context () arising due to the use of "foo" in [...] Possible correction: add (Foo a1) in the context of the signature of the expression type. The first argument is' show ', namely' (foo :: a) 'In the expression: show (foo :: a)
At this moment, I begin to think that I misunderstood something basic. However, I have a strange feeling that similar designs worked for me in the past.