2012-02-15 119 views
0

我不明白这里发生了什么?任何人都可以解释这段代码吗? 这个函数如何计算长度?Haskell高阶函数来计算长度

callength = foldr (\_ n -> 1 + n) 0 

为什么它使用lambda,下划线,下划线和n之间的空格和右边的零?

+7

我认为你会像任何关于Haskell的书的第三章那样找到这个问题的答案。这是一个非常基本的东西。 – 2012-02-15 17:23:36

+5

如果你不喜欢lambda,你可以使用'foldr(((+1)。)。(flip const))0'而不是... – Landei 2012-02-15 18:45:01

+1

你知道'foldr'是什么,它是如何工作的?那么,ehird无论如何都给了它一个相当彻底的解释。 [学习你一个Haskell](http://learnyouahaskell.com/)强烈推荐作为“Haskell入门”书,解释lambda表达式,下划线,折叠,函数等。 – 2012-02-15 21:37:00

回答

18

(\_ n -> 1 + n)只是表示一个函数,它接受两个参数,并返回比第二个参数多一个的参数。下划线仅表示参数被忽略。为了比较,因为没有使用通配符模式(下划线)的顶级声明,这个功能看起来像:

foo x n = 1 + n 

现在,这里是一个例子列表:

[1, 2, 3, 4] 

这其实恰恰是语法糖:

1 : 2 : 3 : 4 : [] 

什么foldr确实是递归与它给出的函数替换每个(:)[]用函数后面的参数()。所以,foldr f z [1, 2, 3, 4]任何fz看起来是这样的:

f 1 (f 2 (f 3 (f 4 z))) 

(这就是为什么foldr (:) []刚刚返回相同的列表,你给它 - 它结束了重构原始列表结构。)

在这情况下,使用功能foo和零0,它看起来像:

foo 1 (foo 2 (foo 3 (foo 4 0))) 

我们知道,foo忽略它的第一个参数,并返回一个铁道部而不是第二个论点。因此,这是相同的:

1 + (1 + (1 + (1 + 0))) 

其为4,则列表的长度。基本上,折叠会忽略列表中的每个元素,并为每个元素添加一个累加器,给出长度。 0用于结束的全过程,并且由于空列表的长度是0

要查看此更详细地,我们可以展开每个呼叫一步步骤:

foldr foo 0 (1 : 2 : 3 : 4 : []) 
foo 1 (foldr foo 0 (2 : 3 : 4 : [])) 
1 + foldr foo 0 (2 : 3 : 4 : []) 
1 + foo 2 (foldr foo 0 (3 : 4 : [])) 
1 + 1 + foldr foo 0 (3 : 4 : []) 
1 + 1 + foo 3 (foldr foo 0 (4 : [])) 
1 + 1 + 1 + foldr foo 0 (4 : []) 
1 + 1 + 1 + foo 4 (foldr foo 0 []) 
1 + 1 + 1 + 1 + foldr foo 0 [] 
1 + 1 + 1 + 1 + 0 
1 + 1 + 1 + 1 
1 + 1 + 2 
1 + 3 
4 
+0

哇。这是Haskell关键基础的一个非常耐心的解释。 +1。 – 2012-02-15 20:23:55