未使用变
首先,明确标记变量为未使用的是_
替换变量的方式。所以,你真的想:
treeFold (\_ ys -> 1 + sum ys)
,因为你写你有一个编译器错误:
treeFold (\ys -> 1 + sum ys)
...这是不一样的东西。
褶皱
其次,我会用手上的例子树评估treeSize
所以你可以看到,有没有神奇的事情:
treeSize (Tree 1 [Tree 2 [], Tree 3 []])
-- Inline definition of 'treeSize'
= treeFold (\_ ys -> 1 + sum ys) (Tree 1 [Tree 2 [], Tree 3 []])
-- Evaluate treeFold
= (\_ ys -> 1 + sum ys) 1 (map (treeFold (\_ ys -> 1 + sum ys)) [Tree 2 [], Tree 3 []])
-- Apply the anonymous function
= 1 + sum (map (treeFold (\_ ys -> 1 + sum ys)) [Tree 2 [], Tree 3 []])
-- Apply the 'map' function
= 1 + sum [ treeFold (\_ ys -> 1 + sum ys) (Tree 2 [])
, treeFold (\_ ys -> 1 + sum ys) (Tree 3 [])
]
-- Apply both 'treeFold' functions
= 1 + sum [ (\_ ys -> 1 + sum ys) 2 (map (treeFold (\_ ys -> 1 + sum ys)) [])
, (\_ ys -> 1 + sum ys) 3 (map (treeFold (\_ ys -> 1 + sum ys)) [])
]
-- Apply the anonymous functions
= 1 + sum [ 1 + sum (map (treeFold (\_ ys -> 1 + sum ys)) [])
, 1 + sum (map (treeFold (\_ ys -> 1 + sum ys)) [])
]
-- map f [] = []
= 1 + sum [ 1 + sum []
, 1 + sum []
]
-- sum [] = 0
= 1 + sum [1 + 0, 1 + 0]
= 1 + sum [1, 1]
-- Apply 'sum'
= 1 + 2
= 3
然而,有一个简单的方法来记住如何treeFold
作品。它所做的就是用您提供的函数替换每个Tree
构造函数。
所以,如果您有:
Tree 1 [Tree 2 [Tree 3 [], Tree 4[]], Tree 5 [Tree 6 [], Tree 7 []]]
...你申请treeFold f
到,它会评估为:
f 1 [f 2 [f 3 [], f 4 []], f 5 [f 6 [], f 7 []]]
treeSum
只是特殊情况下f = (\_ ys -> 1 + sum ys)
:
1 + sum [1 + sum [1 + sum [], 1 + sum []], 1 + sum [1 + sum [], 1 + sum []]]
= 7
Currying
最后一点是如何在Haskell中进行咖啡的工作。当你定义像函数:
foo x y = x + y
...的编译器实际上是desugars两个嵌套函数:
foo = \x -> (\y -> x + y)
这就是为什么你可以部分应用功能,在Haskell只是一个参数。当你写foo 1
,将其转换为:
foo 1
= (\x -> (\y -> x + y)) 1
= \y -> 1 + y
换句话说,它返回一个参数的一个新功能。
在Haskell中,所有函数只需要一个参数,我们通过返回新函数来模拟多个参数的函数。这种技术被称为“咖喱”。
如果你喜欢更传统的主流语言的多参数的方法,你可以通过让函数接受一个元组参数模拟它:
f (x, y) = x + y
然而,这不是真正地道的Haskell,并赢得了”不会给你任何性能改善。
[为什么函数式编程很重要](http://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf)。 – 2013-04-26 23:34:12