3
votes

I'm learning Haskell type classes through UPENN Haskell lecture notes, making my own type class with example code:

class Listable a where
    toList :: a -> [Int]

instance Listable Int where
    toList x = [x]

instance Listable Bool where
    toList True  = [1]
    toList False = [0]

It works with Int and Bool but ghci fails when I add an instance of [Int]:

instance Listable [Int] where
    toList = id

Errors:

Illegal instance declaration for ‘Listable [Int]’

(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 ‘Listable [Int]’

I try several time but all fail:

toList x = id x
toList x = x
toList = \x -> x

How could I fix it?

1
Did you notice the part of the error stating Use FlexibleInstances if you want to disable this ? Plain Haskell is fairly restrictive, especially in type classes; most modern programs make use of several extensions, so now the compiler often suggests which extension you need to turn on.chi
@chi Yep I did, but I thought ghci want me to replace keyword instance with FlexibleInstances , which proved to be dummy.Rahn
Ah, I see :) Extensions are enabled as in the answer below.chi
You can make this even more general: instance Foldable t => Listable (t Int) where toList = Data.Foldable.toListuser2297560

1 Answers

4
votes

Just add the following line at the top of your source file

{-# LANGUAGE FlexibleInstances #-}

This will enable the FlexibleInstances extension that is needed for instance declarations of this form as Haskell 98 doesn't allow them.

Note that you can also enable the extension by adding the -XFlexibleInstances flag when you invoke ghc or ghci, but it is considered a bad practice to do that as it will enable the extension for all your modules. It will also mean that your program will only compile successfully depending on the command line flags passed to the compiler. This is why it is preferable to enable extensions on a per module basis as I explained above.