flawr
flawr

Reputation: 11628

`instance` for concrete type instead of typeclass?

I defined a simple list type:

data MyList a = End
               |Entry a (MyList a)

Instead of deriving (Show) I implemented that explicitly myself for all MyList a where a is an instance of Show.

instance Show a => Show (MyList a)
  where show End = ""
        show (Entry a l) = (show a) ++","++(show l)

This works perfectly fine. Now I wanted to change that such that only MyList String is an instance of Show and to do so I wrote

instance Show (MyList String)
  where show End = ""
        show (Entry a l) = a ++","++(show l)

But this resulted in an error, that I do not understand:

Illegal instance declaration for `Show (MyList String)'
  (All instance types must be of the form (T a1 ... an)
   where a1 ... an are *distinct type variables*,
   and each type variable appears at most once in the instance head.
   Use FlexibleInstances if you want to disable this.)
In the instance declaration for `Show (MyList String)'

Can anyone explain why this will not work and what this error is telling me?

Upvotes: 2

Views: 239

Answers (1)

kirelagin
kirelagin

Reputation: 13606

The error is telling you that standard Haskell does not allow this kind of instance definitions. Exactly as it says,

All instance types must be of the form (T a1 ... an)
where a1 ... an are *distinct type variables*,
and each type variable appears at most once in the instance head.

One of the reasons is that in case you leave both of your instance definitions, the compiler will not know which one to choose for MyList String, as they both match. (You might also want to have a look at the rules for overlapping instances.)

Having this constraint on the form of instance types guarantees that typechecking will always terminate, and while there are of course valid and typecheckable programs with instances not of this form, that is just how it works: some restrictions in Haskell are conservative.

In your particular case just doing what the compiler suggests (i.e. enabling FlexibleInstances) will do the trick and this extension is safe in terms of termination.

Upvotes: 3

Related Questions