11

Given the type class

class Dictionary w where
  insert :: String -> String -> w -> w
  remove :: String -> w -> w
  lookUp :: String -> w ->  String

I can't write

instance Dictionary [(String,String)] where
  insert key value dic = (key,value) : remove key dic
  remove key dic = filter (\entry -> (fst entry) /= key) dic
  lookUp key [] = "not found"
  lookUp key ((k,v):xs) | k == key = v
                        | otherwise = lookUp key xs 

because of

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

... which I don't quite understand. Something like this works:

newtype Dic = Dic [(String,String)]

instance Dictionary Dic where
  insert key value (Dic dic) = Dic $ (key,value) : filter (\entry -> (fst entry) /= key) dic
  remove key (Dic dic) = Dic $ filter (\entry -> (fst entry) /= key) dic
  lookUp key (Dic []) = "not found"
  lookUp key (Dic ((k,v):xs)) | k == key = v
                              | otherwise = lookUp key (Dic xs)  

Is there a better way? Or should I use the suggested compiler directive?

Landei
  • 54,104
  • 13
  • 100
  • 195

2 Answers2

14

The reason is simple. Haskell 98 only allows instances for "unsaturated" types, this is types that are not fixed in their type variables. Read the error message it gives carefully, it exactly describes what the compiler wants to have.

To do what you want, there are basically the two way you already tried:

  • Switch on FlexibleInstances. This is the most common way, as this extension is one of the most used.
  • Wrap it into a newtype. Gives compatibility but is ugly.

Choose one ;)

arrowd
  • 33,231
  • 8
  • 79
  • 110
fuz
  • 88,405
  • 25
  • 200
  • 352
6

You can use pragma of form {-# LANGUAGE FlexibleInstances #-} instead of compiler directive. Scope of such pragma is limited to a single module.

Boris Berkgaut
  • 158
  • 2
  • 8
  • 1
    Sure, but my question was more why I get this error at all, and if there is a less ugly way to instantiate my type class in standard Haskell. – Landei Jan 28 '11 at 10:03