Haskell中的函数定义

gui*_*375 5 haskell function

我开始学习Haskell,"让你学习哈斯克尔的伟大成就!" 我犯了一个奇怪的错误,我无法找到原因.

这是我输入的代码:

let xs = [if x < 3 then "bang" else "boom" | x <- xs]
Run Code Online (Sandbox Code Playgroud)

而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"
Run Code Online (Sandbox Code Playgroud)

但是当我键入:

let boom xs = [if x < 3 then "bang" else "boom" | x <- xs]
Run Code Online (Sandbox Code Playgroud)

这是本书的例子,我没有任何问题.

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

sep*_*p2k 13

你的定义xs是递归的,就是你在xs自己的定义中使用.我不认为那是你的意图.

由于你在列表推导中使用"bang"和"boom"内部,Haskell知道xs必须是一个字符串列表(因为xs它等于列表推导的结果).此外,你说这x是xs(x <- xs)的元素,所以x必须是一个字符串(又名[Char]).不过你这样做x < 3,这意味着这x是一个数字.错误消息表示"字符串不是数字".


Dan*_*her 7

尝试给表达式一个类型.

xs = [if x < 3 then "bang" else "boom" | x <- xs]
Run Code Online (Sandbox Code Playgroud)

所以xs是一个列表,我们还不知道它的元素有什么类型,所以让我们看看下一个.列表元素是

if x < 3 then "bang" else "boom"
Run Code Online (Sandbox Code Playgroud)

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

所以xs :: [String].由于x来自描述列表元素的表达式是从列表xs本身中获取的,因此它String也是,并且在比较中使用

if x < 3
Run Code Online (Sandbox Code Playgroud)

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

3 :: Num a => a
Run Code Online (Sandbox Code Playgroud)

所以从表达来看x < 3,我们有

  • Num来自文字的约束,
  • String来自s x列表的事实的类型String.

因此,我们需要一个Num实例String来获得一个良好类型的表达式.

通常,没有Num实例String(有用的是什么样的?),因此您会遇到类型错误.

如果xs是函数的参数,

boom xs = [if x < 3 then "bang" else "boom" | x <- xs]
Run Code Online (Sandbox Code Playgroud)

没有理由为什么x应该这样String,因此这是有效的.