我开始学习Haskell,“让你学习哈斯克尔的伟大成就!”我犯了一个奇怪的错误,我无法找到原因。
以下是我输入的代码:
let xs = [if x < 3 then "bang" else "boom" | x <- xs]
GHCi中的错误文本:
No instance for (Num [Char])
arising from the literal `3'
Possible fix: add an instance declaration for (Num [Char])
In the second argument of `(<)', namely `(3)'
In the expression: x < (3)
In the expression: if x < (3) then "bang" else "boom"
但是当我输入时:
let boom xs = [if x < 3 then "bang" else "boom" | x <- xs]
这是本书的例子,我没有任何问题。
有人可以解释我的错误吗?
答案 0 :(得分:13)
您对xs
的定义是递归的,即您在其自己的定义中使用xs
。我认为这不是你想要的。
由于您在列表推导中使用"bang"
和"boom"
,Haskell知道xs
必须是字符串列表(因为xs
等于结果列表理解)。此外,您说x
是xs
(x <- xs
)的元素,因此x
必须是字符串(a.k.a。[Char]
)。但是你做x < 3
,这意味着x
是一个数字。错误消息表示“字符串不是数字”。
答案 1 :(得分:7)
尝试给表达式一个类型。
xs = [if x < 3 then "bang" else "boom" | x <- xs]
所以xs
是一个列表,我们还不知道它的元素有什么类型,所以让我们看看下一个。列表元素是
if x < 3 then "bang" else "boom"
是String
类型的表达式(又名[Char]
)。
所以xs :: [String]
。由于描述列表元素的表达式中的x
取自列表xs
本身,因此它也是String
,用于比较
if x < 3
现在,3
是一个整数文字,因此它是多态的,类型为
3 :: Num a => a
所以从表达式x < 3
来看,我们有
Num
约束,String
类型x
来自String
s列表中的Num
。因此,我们需要一个String
Num
实例才能拥有一个类型良好的表达式。
通常,String
没有xs
个实例(有用的是什么样的?),因此会出现类型错误。
如果boom xs = [if x < 3 then "bang" else "boom" | x <- xs]
是函数的参数,
x
没有理由认为String
的类型应为{{1}},因此可行。
答案 2 :(得分:0)
let xs = ...
表示xs等于“bang”和/或“boom”的列表,但是条件指出那些元素应该测试为&lt; 3,这通常用数字而不是字符串来完成。
let boom xs =...
将函数“boom”等同于等式的右边,其中参数'xs'是从中绘制要测试的元素&lt; 3的列表。