2012-01-27 21 views
9

能有人请解释或提供对函数组合是如何工作的有关懒惰一些资源?懒惰和函数组合(Haskell中,二郎)

例如如何在Haskell filter (/='W') . map toUpper $ "justaword"工作相比,它在二郎对方是不是懒惰?

回答

13

每次另一个字符被征求(或结束的通知),则下一个字符 - 如果有的话 - 被映射为大写,即相比于“W”,如果不相等的递送。

filter (/= 'W') . map toUpper $ "justaword" 
~> filter (/= 'W') (toUpper 'j' : map toUpper "ustaword") 
~> filter (/= 'W') ('J' : map toUpper "ustaword") 
~> 'J' : filter (/= 'W') (map toUpper "ustaword") 

现在的第一个字符是可用的,所以对于像null查询或功能,如take 1,没有进一步的工作。如果消费者要求更多的字符,它们将被逐个生产,直到字符串到达​​末尾。

实施例:

Prelude Data.Char> take 10 . filter (/= 'W') . map toUpper $ repeat 't' 
"TTTTTTTTTT" 

repeat产生无穷列表,但只要只有有限部分被消耗,计算完成在有限时间内。但是,take 10 . filter (/= 'W') . map toUpper $ repeat 'w'不会终止,因为没有任何生成的字符通过filter到达take 10

+0

谢谢你的输入反应很大:)是否有可能写在严格的语言代码(无模拟懒惰)?或者在严格的语言中,该列表将遍历两次,一次用于映射,一次用于过滤器,从beginnig开始? – Adi 2012-01-27 11:45:11

+1

@Adi:是的,会有两个列表遍历。地图将返回一个新的中间列表,这是传递给过滤器,将经过比,并返回另一个列表 – newacct 2012-01-27 11:56:53

+5

在严格的(急切,而)语言,一个人必须要模拟懒惰,以获得相同的行为。有些语言比其他语言更容易,我宁愿在erlang或F#中执行,而不是在C中(尽管我知道C但几乎没有erlang或F#:)。是否有两个遍历或一个渴望的语言取决于编译器。原则上,过滤器和映射可以融合,但通常编译器需要证明映射函数和过滤器谓词的纯度才能做到这一点。所以我预计在大多数情况下会有两次遍历,这个证明很难。 – 2012-01-27 12:00:08