输入有关"FlexibleInstances"的类问题

Lan*_*dei 11 haskell typeclass

鉴于类型类

class Dictionary w where
  insert :: String -> String -> w -> w
  remove :: String -> w -> w
  lookUp :: String -> w ->  String
Run Code Online (Sandbox Code Playgroud)

我写不出来

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 
Run Code Online (Sandbox Code Playgroud)

因为

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)]'
Run Code Online (Sandbox Code Playgroud)

......我不太明白.像这样的东西有效:

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)  
Run Code Online (Sandbox Code Playgroud)

有没有更好的办法?或者我应该使用建议的编译器指令?

fuz*_*fuz 14

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

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

  • 打开FlexibleInstances.这是最常用的方式,因为此扩展是最常用的方法之一.
  • 裹成一个NEWTYPE.提供兼容性但很难看.

选一个 ;)


Bor*_*aut 6

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