Задача класса типа относительно "FlexibleInstances" - PullRequest
11 голосов
/ 28 января 2011

Учитывая тип класса

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

Я не могу написать

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 

из-за

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)]'

... что я не совсем понимаю. Примерно так работает:

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)  

Есть ли лучший способ? Или я должен использовать предложенную директиву компилятора?

Ответы [ 2 ]

14 голосов
/ 28 января 2011

Причина проста.Haskell 98 допускает только экземпляры для «ненасыщенных» типов, это типы, которые не зафиксированы в своих переменных типов.Внимательно прочитайте сообщение об ошибке, которое точно описывает то, что хочет иметь компилятор.

Чтобы сделать то, что вы хотите, есть два способа, которые вы уже попробовали:

  • Switchна FlexibleInstances .Это наиболее распространенный способ, так как это расширение является одним из наиболее используемых.
  • Оберните его в newtype .Дает совместимость, но безобразно.

Выберите один;)

6 голосов
/ 28 января 2011

Вы можете использовать прагму формы {-# LANGUAGE FlexibleInstances #-} вместо директивы компилятора.Сфера применения такой прагмы ограничена одним модулем.

...