无法匹配预期类型'(Char,Bool) - > Bool'实际类型'Char'

时间:2018-02-03 05:04:37

标签: haskell

我正在学习"Programming in Haskell"一书的第8章中的部分重言式检查。

enter image description here

有提及的代码

eval :: Subst -> Prop -> Bool
eval _ (Const b) = b
eval s (Var x) = find x s
eval s (Not p) = not (eval s p)
eval s (And p q) = eval s p && eval s q
eval s (Imply p q) = eval s p <= eval s q 

编译此代码时出现以下错误。

tautology_checker.hs:26:23: error:
    • Couldn't match expected type ‘(Char, Bool) -> Bool’
              with actual type ‘Char’
    • In the first argument of ‘find’, namely ‘x’
      In the expression: find x s
      In an equation for ‘eval’: eval s (Var x) = find x s
   |
26 | eval s (Var x) = find x s
   |      

我检查拼写错误和拼写错误。这似乎是正确的。

我的代码是here

请帮我解决此错误。

2 个答案:

答案 0 :(得分:4)

您似乎无意中使用了Prelude的标准函数find,其类型为:

Foldable t => (a -> Bool) -> t a -> Maybe a

或者,专门列出:

(a -> Bool) -> [a] -> Maybe a

本书希望您使用一些其他 find函数(可能在文本的其他地方定义),类似于:

(Eq a) => a -> [(a, b)] -> b

或者,在您的情况下:

Char -> [(Char, Bool)] -> Bool

你给它x作为它的第一个参数,类型为Char,但它期望类型为(Char, Bool) -> Bool的函数,因为(Char, Bool)是元素列表的类型。这是你得到的类型错误的来源。

您可以使用标准函数find x s替换lookup

lookup :: Eq a => a -> [(a, b)] -> Maybe b

结合fromJust(在未绑定变量时抛出错误)等内容,例如fromJust (lookup x s)。您还可以使用find' x s = fromMaybe (error ("unbound variable '" ++ [x] ++ "'")) (lookup x s)之类的内容获取更详细的错误消息,或者fromMaybe False(假设未绑定的变量为False),使用fromMaybe中的Data.Maybe

答案 1 :(得分:2)

最终在您的代码中使用的函数find来自Data.List并且具有签名find :: (a -> Bool) -> [a] -> Maybe a。此函数尝试查找给定列表中与给定谓词匹配的元素。

但是,从代码中使用此函数的方式来看,您似乎假设签名find :: k -> Assoc k v -> v,其语义是在关联列表中按键定位值。这就是我实现这样功能的方法:

find :: Eq k => k -> Assoc k v -> v
find k ((k', v) : _) | k == k' = v
find k (_ : tail) = find k tail

我没有这本书,所以我无法确定,但我的猜测是该书实际上在某个地方实际定义了这个函数,可能在它定义类型Assoc本身的同一个地方。您已在代码中包含Assoc的定义,但忘记包含find的定义。

另请注意,以这种方式定义的函数find partial :当给定的关联列表不包含给定的键时,它不知道要返回什么。为了使其成为总计,需要返回Maybe v而不是v。请记住一些事情。