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

tib*_*bbe 14 haskell fusion

我们可以xs在表达式的列表中融合两个遍历

(map f xs, map g xs)
Run Code Online (Sandbox Code Playgroud)

像这样

unzip (map (\x -> (f x, g x)) xs)
Run Code Online (Sandbox Code Playgroud)

有没有自动进行这种融合的研究?

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

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

Pet*_*lák 4

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

编辑:为了给出这个特定问题的例子,我们可以写:

{-# 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)
Run Code Online (Sandbox Code Playgroud)

(规则中的顶级函数名称是(,) :: a -> b -> (a, b))。编译时,您将看到如何应用规则。dump-rule-firings应用规则时选项会显示一条消息,并-ddump-rule-rewrites详细显示每个规则应用程序 - 请参阅7.14.6。控制重写规则中发生的事情