学习Haskell地图,折叠,循环和递归
作为编程启蒙之旅的一部分(从程序到OOP到并发到现在的功能),我只是将自己的脚趾蘸到了Haskell的世界中。
我一直在尝试一个在线Haskell评估器。
不过,我现在陷入了一个问题:
创建一个简单的函数,给出数组数组的总和。
在程序语言中,这对我来说很简单(使用递归)(c#):
private int sum(ArrayList x, int i)
{
if (!(x.Count < i + 1)) {
int t = 0;
t = x.Item(i);
t = sum(x, i + 1) + t;
return t;
}
}
所有非常好的,但是我在Haskell失败的尝试是这样的:
let sum x = x+sum in map sum [1..10]
这导致了以下错误(来自上述网站):
Occurs check: cannot construct the infinite type: a = a -> t
请记住,我在过去的30分钟内只使用了Haskell!
我不是简单地寻找答案,而是更多地解释它。
我不是简单地寻找答案,而是更多地解释它。
在=的左边,你可以使用sum
作为应用于x
的函数。 编译器不知道x
的类型,因此编译器使用类型变量a
来表示“ x
的类型”。 因此编译器不知道函数sum
的结果类型,所以它选择另一个类型变量,这个类型t
来表示结果类型。 现在在左边,编译器认为x
的类型是a -> t
(接受a
和返回t
函数)。
在=的右边添加x
和sum
。 在Haskell中,可以添加所有类型的数字,但只有在具有相同类型时才可以添加两个数字。 所以在这里,编译器假定sum
的类型与x
相同,即键入a
。
但是在Haskell中,一个标识符有一种类型 - 可能是一种whangdilly复杂类型,但是一种类型。 这包括sum
,它的类型应该在`sign的两边相同,所以编译器试图解决方程式
a = a -> t
a
和t
没有解决这个等式的值。 它根本无法完成。 没有a
这样的a
等于一个接受自己作为参数的函数。 因此出现错误信息
cannot construct the infinite type: a = a -> t
即使所有的解释,这不是一个很好的错误信息,是吗?
欢迎来到Haskell :-)
PS您可能会喜欢尝试“氦气,用于学习Haskell”,这为初学者提供了更好的错误信息。
'sum'取一个值列表并将其减少为一个值。 你可以把它写成一个显式循环(记住Haskell没有循环关键字,但使用递归)。 请注意,根据列表的形状,定义有两个部分:
mysum [] = 0
mysum (x:xs) = x + mysum xs
或者更有效率地采用尾递归风格:
mysum xs = go 0 xs
where
go n [] = n
go n (x:xs) = go (n+x) xs
不过,Haskell拥有丰富的控制结构库,可以在懒惰列表上运行。 在这种情况下,可以使用reduce函数将列表减少为单个值:折叠。
所以mysum可以写成:
mysum xs = foldr (+) 0 xs
例如:
Prelude> foldr (+) 0 [1..10]
55
你的错误是使用地图,它一次转换一个列表,一个元素,而不是折叠。
我建议你首先介绍Haskell,也许是“Haskell编程”,以便了解函数式编程的核心概念。 在这个问题中描述了其他很好的介绍性材料。
你需要阅读一个好的教程,有一些大的误解。
首先我要假设你是指列表而不是数组。 数组存在于Haskell中,但它们不是初学者会遇到的。 (更不用说你正在使用[1..10],它是数字1到10的列表)。
你想要的功能实际上是内置的,并且调用sum,所以我们必须调用我们的其他东西,new_sum:
new_sum [] = 0
new_sum (h:t) = h + (sum t)
链接地址: http://www.djcxy.com/p/80791.html
上一篇: Learning Haskell maps, folds, loops and recursion
下一篇: How much time have you invested in order to have a good grasp on Haskell?