Hi. Hopefully some of you can help me clear up this confusion I have. I'm sorry for the bad title - if anyone has suggestions I'll change it.
Let's set up some context first. I've reduced everything down to the essentials, so bear with me if the example code below is somewhat contrived. Let's 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 Type a
an instance of, say, Show
whenever a
is an instance of both Foo
and Show
(Show
was chosen to avoid defining another typeclass). So how do we want Type a
to be an instance of Show
? Well, unless we're crazy, we'd of course 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)
That's all great and works fine. But say that for some inexplicable reason, we'd like show
to output whatever foo :: a
looks/shows like! In our contrived setting I cannot imagine why we'd want that, but let's say we do. Shouldn't
instance (Foo a, Show a) => Show (Type a) where
show _ = show foo
do the trick?
Alas, GHC says
Ambiguous type variable 'a' in the constraints: 'Foo a' [...] 'Show a'
Hmm, I thought, so maybe GHC can't figure out which foo
I'm talking about. Do I mean foo :: Type a
or foo :: a
? Changing the previous snippet to
instance (Foo a, Show a) => Show (Type a) where
show _ = show (foo :: a)
gives me
Could not deduce (Foo a1) from the context () arising from a use of 'foo' at [...] Possible fix: add (Foo a1) to the context of an expression type signature In the first argument of 'show', namely '(foo :: a)' In the expression: show (foo :: a)
At this point I'm starting to think I've misunderstood something basic. Yet, I have the strange feeling that similar constructions have worked for me in the past.