Degeneration of typeclass instance declaration using constant value

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.

+4
source share
1 answer

I think the problem is that type variables are not bound to definitions. That is, in

 instance (Foo a, Show a) => Show (Type a) where show _ = show (foo :: a) 

a in the second line is different from a in the first line, so in the error message it appears as a1 . See http://www.haskell.org/haskellwiki/Scoped_type_variables . If this is a problem, this should work (I don't have GHC on this machine):

 asTypeOf :: a -> a -> a asTypeOf ab = a instance (Foo a, Show a) => Show (Type a) where show (Type x) = show (foo `asTypeOf` x) 
+6
source

All Articles