我正在学习"Programming in Haskell"一书的第8章中的部分重言式检查。
有提及的代码
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。
请帮我解决此错误。
答案 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
。请记住一些事情。