Как я могу сплавить две карты по одному списку?

Мы могли бы сплавить два обхода по списку xs в выражении

(map f xs, map g xs)

так

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

Есть ли какой-либо поиск автоматического выполнения такого рода слияния?

(Здесь существует риск создать утечку пространства, если один из возвращенных списков будет потреблен раньше другого. Меня больше интересует предотвращение дополнительного обхода xs, чем сохранение пробела.)

Изменить: я на самом деле не пытаюсь применить слияние к фактическим спискам Haskell в памяти, где это преобразование может не иметь смысла в зависимости от того, может ли unzip соединить его с потребителем. У меня есть настройка, где я знаю, что unzip может сработать (см. "FlumeJava: простые, эффективные параллельные параллельные потоки данных" ).

Ответы

Ответ 1

Также не полностью автоматический, но вы можете дать 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)

(имя функции верхнего уровня в правиле (,) :: a -> b -> (a, b)). При компиляции вы увидите, как применяются правила. Параметр dump-rule-firings показывает сообщение, когда применяется правило, и -ddump-rule-rewrites отображает каждое приложение правила подробно - см. 7.14.6. Контроль выполнения правил перезаписи.

Ответ 2

Мне удалось найти два ресурса, в которых упоминаются функции fusion (un-) zip-like, по крайней мере, кратко:

Йозеф Свеннингссон. "Ярлык Fusion для накапливания параметров и zip-подобных функций" http://www.cse.chalmers.se/~josefs/publications/fusion.pdf

Дункан Коуттс. "Stream Fusion: практическое сочетание горячих клавиш для типов коиндуктивной последовательности" https://community.haskell.org/~duncan/thesis.pdf

Ни один из ресурсов не упоминает об этом виде "sibling fusion" явно.