如何在同一列表中融合两张地图?

时间:2012-09-03 04:29:10

标签: haskell fusion

我们可以在表达式

中的列表xs上融合两次遍历
(map f xs, map g xs)

喜欢这样

unzip (map (\x -> (f x, g x)) xs)

是否有自动执行此类融合的研究?

(如果其中一个返回的列表在另一个之前消耗,则存在创建空间泄漏的风险。我更有兴趣防止额外遍历超过xs而不是节省空间。)

编辑:我实际上并不打算将融合应用于实际的内存中Haskell列表,根据unzip是否可以与其消费者融合,这种转换可能没有意义。我有一个设置,我知道unzip可以融合(参见“FlumeJava:简单,高效的数据并行管道”)。

2 个答案:

答案 0 :(得分:4)

也不是全自动的,但你可以给GHC一个这样的重写规则列表。请参阅7.14 Rewrite rulesUsing rules。然后编译器使用这些规则在编译时优化您的程序。 (注意,编译器决不会检查规则是否有意义。)

编辑:举一个例子来说明这个问题,我们可以写一下:

{-# OPTIONS_GHC -fenable-rewrite-rules -ddump-rule-firings -ddump-rule-rewrites #-}

import Data.Char

{-# RULES
"map/zip" forall f g xs. (,) (map f xs) (map g xs) = unzip (map (\x -> (f x, g x)) xs)
   #-}

main :: IO ()
main = let x = "abCD" in
        print $ (,) (map toUpper x) (map toLower x)

(规则中的顶级函数名称为(,) :: a -> b -> (a, b))。编译时,您将看到如何应用规则。选项dump-rule-firings会在应用规则时显示一条消息,-ddump-rule-rewrites会详细显示每个规则应用程序 - 请参阅7.14.6. Controlling what's going on in rewrite rules

答案 1 :(得分:3)

我设法找到两个资源,提到融合(un-)zip函数,至少是短暂的:

约瑟夫·斯文宁森。 “用于累积参数和类似Zip的功能的快捷方式融合” http://www.cse.chalmers.se/~josefs/publications/fusion.pdf

邓肯Coutts。 “Stream Fusion:用于同源序列类型的实用快捷方式融合” https://community.haskell.org/~duncan/thesis.pdf

两种资源都没有明确提到这种“兄弟融合”。