好吧,让我们来看看为curried functionfoldr
类型签名:
>:t foldr
foldr :: (a -> b -> b) -> b -> [a] -> b
所以foldr
取一个二元函数(即a->b->b
),一个b
值,a
值的列表,并返回一个值为b
。
让我们也看看documentation为foldr
以获得更明确的定义:
foldr相似,适用于二元运算,初始值(操作者通常是 右身份),以及列表中,降低了使用 二元运算符的列表中,由右至左:
现在,让我们来看看类型签名myConcat xs = foldr (++) []
> :t myConcat
myConcat :: t -> [[a]] -> [a]
嗯......这不是我们想要的...
的问题是,你永远不提供foldr
[a]
类型的值。所以,现在,myConcat
需要一定的价值,任何类型,以满足xs
和[a]
类型的值来完成foldr (++) []
,如:
> myConcat 2 [[1,2],[3,4]]
[1,2,3,4]
> myConcat Nothing [[1,2],[3,4]]
[1,2,3,4]
这样的作品,但第一个参数是太浪费了。
然而,如果我们传递xs
值到foldr (++) []
,如:
myConcat xs = foldr (++) [] xs
,并检查它的类型签名
> :t myConcat
myConcat :: [[a]] -> [a]
嗯,好多了。现在myConcat使用xs
来完成foldr
函数。
另外,myConcat = foldr (++) []
也有效,实际上是point-free style programming的一个例子。如果我们检查既然我们已经通过partial application提供foldr
它的前两个参数的foldr (++) []
类型签名,
> :t foldr (++) []
foldr (++) [] :: [[a]] -> [a]
,我们得到了一个功能回到那个意志需要[[a]]
值,做我们想要的!所以我们只是将它分配给一个名称,它的工作方式就像上面的例子,但我们不需要明确地传递参数!
> let myConcat = foldr (++) []
> :t myConcat
myConcat :: [[a]] -> [a]
> myConcat [[1,2],[3,4]]
[1,2,3,4]
+1:一个非常容易理解的解释;你碰巧有一个Haskell相关的博客吗?我喜欢你的风格。 :-) –
@Frerich Raabe:谢谢!事实上,我有一个博客,主要是关于Scala,不过现在又是Haskell,但不幸的是它是德文的:http://dgronau.wordpress。com/ – Landei
非常感谢你,我现在明白了:)很好的解释 – Adi