2012-09-03 24 views
14

Podríamos fusionamos dos recorridos más de la lista xs en la expresión¿Cómo puedo fusionar dos mapas en la misma lista?

(map f xs, map g xs) 

al igual que

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

¿Hay alguna reasearch en la realización de este tipo de fusión de forma automática?

(Hay un riesgo de crear una fuga de espacio aquí, si una de las listas devueltas se consume antes que el otro estoy más interesado en la prevención del recorrido extra sobre xs que el ahorro de espacio..)

Edit: De hecho, no estoy buscando aplicar la fusión a las listas reales de Haskell en memoria, donde esta transformación podría no tener sentido dependiendo de si el unzip se puede fusionar con su (s) consumidor (s). Tengo una configuración donde sé que unzip puede fusionarse (ver "FlumeJava: tuberías de datos paralelas fáciles y eficientes").

+2

No es automático, pero bastante agradable de todos modos: http://squing.blogspot.com/2008/11/beautiful-folding.html –

+1

A menos que el resultado de esto se fusione con otra cosa, la sobrecarga de crear los pares y descomprimirlos ser más grande que el costo del recorrido extra. – augustss

+1

@augustss ¡No si el cruce está sobre un archivo enorme! No estoy planeando aplicar esto a listas reales. – tibbe

Respuesta

4

También no es totalmente automático, pero puede darle a GHC una lista de reglas de reescritura como esa. Ver 7.14 Rewrite rules y Using rules. Entonces el compilador usa estas reglas para optimizar su programa al compilar. (Tenga en cuenta que el compilador de ninguna manera comprueba si las reglas tiene ningún sentido.)

Editar: Para dar un ejemplo de este problema en particular, podemos escribir:

{-# 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) 

(el más alto nivel nombre de la función en la regla es (,) :: a -> b -> (a, b)). Al compilar, verá cómo se aplican las reglas. La opción dump-rule-firings muestra un mensaje cuando se aplica una regla y -ddump-rule-rewrites muestra cada aplicación de regla en detalle - consulte 7.14.6. Controlling what's going on in rewrite rules.

+0

No creo que podamos escribir una regla para que coincida con este tipo de expresiones. Las reglas de GHC deben comenzar con un nombre de función. – tibbe

3

He conseguido encontrar dos recursos que menciona la fusión (des) zip como funciones, al menos brevemente:

Josef Svenningsson. "Acceso directo de fusión para acumular Parámetros Funciones & Zip-como" http://www.cse.chalmers.se/~josefs/publications/fusion.pdf

Duncan Coutts. "Stream Fusion: Práctica fusión de acceso directo para tipos de secuencia coinductiva" https://community.haskell.org/~duncan/thesis.pdf

Ninguno de los dos recursos menciona explícitamente este tipo de "fusión de hermanos".

+1

No vi esta presentación, pero aquí están las diapositivas de Josef sobre [TupleFusion] (http://wiki.portal.chalmers.se/cse/uploads/FP/Josef_TupleFusion.pdf). – danr

+0

[Hacia una estrategia automatizada de tupling] (http://dl.acm.org/citation.cfm?id=154643) podría ser interesante. –