什么是Haskell的流融合


67

什么是Haskell的Stream Fusion,该如何使用?


1
您需要知道哪些内容尚未在本文中介绍吗?如果是这样,您能更具体吗?
2009年


1
注意:还有一种叫做“列表融合”的东西,它会自动使用许多内置功能:downloads.haskell.org/~ghc/7.4.2/docs/html/users_guide/…并查看conscientiousprogrammer.com/blog/2015 / 12/19 /…关于如何检查它是否被使用(或尝试stack build --ghc-options "-ddump-rule-firings -ddump-rule-rewrites" && find .stack-work/ -name '*dump-rule*')。
2013年

Answers:


65

Logan指向的论文很棒,但是有点困难。(只问我的学生。)“流融合的工作原理”也很重要,而“流融合是什么以及如何使用它”只是很小一部分。

流融合解决的问题是,编写的功能代码经常分配中间列表,例如,为了创建节点号的无限列表,您可能会编写

nodenames = map ("n"++) $ map show [1..]

天真的代码会分配一​​个无限的整数列表[1, 2, 3, ...],一个无限的字符串列表["1", "2", "3", ...],最后是一个无限的名称列表["n1", "n2", "n3", ...]。分配太多了。

流融合的作用是将类似的定义nodenames转换为使用递归函数的定义,该递归函数仅分配结果所需的内容。通常,消除中间列表的分配称为砍伐森林

要使用流融合,您需要编写非递归列表函数,这些函数使用GHC票务915mapfoldr等)中描述的流融合库中的函数,而不是显式递归。该库包含所有Prelude函数的新版本,这些函数已被重写以利用流融合。显然,这些内容已计划在下一版GHC(6.12)中使用,但不在当前的稳定版本(6.10)中。如果您想使用库,Porges的回答中有一个很好的简单解释。

如果您实际上想要解释流融合的工作原理,请提出另一个问题-但这要困难得多。


6
是否有任何计划使其成为前奏列表的默认行为?
Thomas Ahle 2013年

1
应用程序$和成分之间在融合方面有区别.吗?
CMCDragonkai '16

1
Prelude的功能是以某种方式标记的还是什么?即为什么它不能用于自制的递归函数?
Hi-Angel

1
GHC 8.0.2是否支持Prelude中的默认列表融合?
Chinaxing '17

13

据我所知,与Norman所说的相反,目前在GHC的基础上尚未实现流融合(即,您不能仅使用Prelude函数)。有关更多信息,请参见GHC票务915

要使用流融合,您需要安装流融合库,导入Data.List.Stream(也可以导入Control.Monad.Stream),并且仅使用该模块中的函数而不是Prelude函数。这意味着导入Prelude隐藏所有默认列表函数,而不使用[x..y]构造或列表推导。


-2

是不是正确的,当GHC在6.12中默认使用这些新功能时,它们也将以非递归方式实现[x..y]并列出理解吗?因为它们不是正确的行,唯一的原因是它们是内部的,并不是真正用Haskell编写的,而是出于速度和/或因为您无法重新定义该语法而更像关键字。


[ x .. y ]不是关键字。在窗帘的背后,它变成了enumFromTo x y,因此这没有什么“神奇”的东西。
Willem Van Onsem
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.