0
votes

I feel like this should be really easy, but i am stuck at this point for quite some time.

Is it possible in haskell to create an instance of a type class for a list of certain data types?

What i want to achieve is the following.

class Rename a where
    findSub :: a -> a

-- A 'normal' instance would look like this
instance Rename Atom where
    findSub ......

-- Now i want to acchieve something like this
instance Rename ([] Atom) where
    findSub ......

How ever when i write this i get the following error:

* Illegal instance declaration for `Rename [Atom]'
        (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 `Rename ([] Atom)'
Failed, modules loaded: none.

I would like to know how to fix this and why this is not allowed.

Thanks in advance.

1

1 Answers

3
votes

It just requires a language extension, since this form of instance is not technically allowed by the Haskell 98 standard. When the error message says to enable an extension, usually just do it[1]. FlexibleInstances is a very common and accepted extension, so just put

{-# LANGUAGE FlexibleInstances #-}

at the top of the file.


Alternatively, often times such instances can be defined "recursively", in which case you don't need the extension, but besides that you get more instances for free, and more guarantees because the type is more general. See if you can define

instance (Rename a) => Rename [a] where
    findSub ...

instead, using only the fact that a is a Rename rather than it being specifically an Atom. When you can define instances this way, it is a good sign that your design is on the right track.


[1] There are a few exceptions, such as UndecidableInstances or IncoherentInstances, which sometimes indicates that you have a wrong idea about how typeclass resolution works.