显然,我的类型签名已关闭。我已经发现了原因。现在,我有兴趣了解更多有关GHCI推断签名的错误信息。我试图让这段代码起作用:
elemNum :: (Eq a, Num b) => a -> [a] -> b
elemNum e l = f e l
where f _ [] = [] -- this was my typo, supposed to read 0
f e (x:xs)
| x == e = 1 + f e xs
| otherwise = f e xs
由于上述原因,它显然不起作用;但是,如果我删除了我的签名,它会编译(不确定原因,请解释),并且我得到了这个签名:
elemNum :: (Num [a], Eq t) => t -> [t] -> [a]
我之前从未见过类型类Num [a]
。这意味着什么,以及它与(Num a) => [a]
的比较。
答案 0 :(得分:8)
Num a
表示类型a
可以视为数字;例如。您可以将两个a
添加到一起以获得新的a
,或者您可以否定a
并获得a
。 Integer
和Double
属于此类别。
相应地,Num [a]
表示类型[a]
可以被视为数字。即您可以将两个a
列表添加到一起,以获取a
的新列表。这不太可能有意义,因为没有列表是数字(默认情况下)。这意味着您正在处理列表,就像它是一个数字,导致GHC得出结论,您必须希望列表像数字一样,从而添加适当的约束。
这样的约束可能来自如下函数:
foo (x:xs) = xs + 1
xs
模式匹配作为列表的尾部,因此它本身就是一个列表,然后您添加它,将列表视为数字。
答案 1 :(得分:2)
Num [a]约束意味着list是Num类型的实例。
foo :: Num a => [a]
是作为Num类型类
的实例的值列表bar :: Num [a] => [a]
是值列表,它是Num类型类的实例。这意味着您可以使用Num中的所有函数并从数字文字构造列表,因此下面的代码有效,但需要FlexibleContexts
bar :: Num [a] => [a]
bar = 42
P.S。你这里不需要辅助功能。 elemNum e l = f el⇒elemNum= f。所以你可以把你的函数写成
elemNum _ [] = 0
elemNum e (x:xs)
| x == e = 1 + f e xs
| otherwise = f e xs