5

我开始通过“Learn You a Haskell for Great Good!”来学习 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]

这是书中的例子,我没有任何问题。

有人可以解释我的错误吗?

4

3 回答 3

13

您的定义xs是递归的,即您xs在其自己的定义中使用。我不认为那是你的本意。

由于您在列表推导中使用"bang"and "boom",因此 Haskell 知道它xs必须是一个字符串列表(因为xs等于列表推导的结果)。此外,您说这xxs( x <- xs) 的一个元素,因此x必须是一个字符串 (aka [Char])。但是,您这样做x < 3,这意味着这x是一个数字。错误消息的意思是“字符串不是数字”。

于 2013-04-07T20:31:40.620 回答
7

尝试给表达式一个类型。

xs = [if x < 3 then "bang" else "boom" | x <- xs]

列表也是如此xs,我们还不知道它的元素有什么类型,所以让我们接下来看看。列表元素是

if x < 3 then "bang" else "boom"

这是类型String(aka [Char]) 的表达式。

所以xs :: [String]。由于xfrom 描述列表元素的表达式取自列表xs本身,因此它也是 a String,并且用于比较

if x < 3

现在,3是一个整数文字,因此它是多态的并且具有类型

3 :: Num a => a

所以从表达式x < 3中,我们有

  • Num来自文字的约束,
  • 从 s列表中提取String的事实的类型。xString

因此,我们需要一个具有良好类型表达式的Num实例。String

通常,没有Num实例String(有用的会是什么样子?),所以你会得到一个类型错误。

如果xs是函数的参数,

boom xs = [if x < 3 then "bang" else "boom" | x <- xs]

没有理由应该的类型x应该是String,因此有效。

于 2013-04-07T20:35:18.687 回答
0
let xs = ... 

表示 xs 等于 "bang" 和/或 "boom" 的列表,但条件规定应测试这些元素是否小于 3,这通常使用数字而不是字符串来完成。

let boom xs =...

将函数 'boom' 等同于等式的右侧,其中参数 'xs' 是从中提取要测试 <3 的元素的列表。

于 2013-04-07T20:51:15.470 回答