输入有关“FlexibleInstances”的类问题

时间:2011-01-28 09:29:05

标签: haskell typeclass

给出类型类

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 个答案:

答案 0 :(得分:14)

原因很简单。 Haskell 98只允许“不饱和”类型的实例,这是在类型变量中没有修复的类型。仔细阅读它提供的错误消息,它准确地描述了编译器想要的内容。

要做你想做的事,你基本上已经尝试了两种方式:

  • 启用 FlexibleInstances 。这是最常用的方式,因为此扩展是最常用的扩展方式之一。
  • 将其包装成 newtype 。提供兼容性但很难看。

选择一个;)

答案 1 :(得分:6)

您可以使用{-# LANGUAGE FlexibleInstances #-}形式的编译指示而不是编译器指令。此类编译指示的范围仅限于单个模块。