2012-04-12 19 views
9

Me gustaría generar un producto cartesiano bastante grande pero finito en Haskell, que necesito repetir (piense en la función de partición de un modelo de campo medio). Lo natural que hacer sequence utiliza, como esto:Producto cartesiano perezoso en Haskell

l = sequence $ replicate n [0,1,2] 

Desafortunadamente, para gran n, esto no encaja en la memoria y se me termina el montón tan pronto como le pido length l por ejemplo. Necesitaría una manera de hacer lo mismo perezosamente. Terminé "redescubrimiento" base-3 aritmética, de esta manera,

nextConfig []  = [] 
nextConfig (0:xs) = 1:xs 
nextConfig (1:xs) = 2:xs 
nextConfig (2:xs) = 0:(nextConfig xs) 

ll = take (3^n) $ iterate nextConfig $ replicate n 0 

(que funciona) pero se siente como reinventar la rueda, y además es demasiado específica. ¿Cuál sería una mejor manera de generar el producto?

+0

¿Le importa el orden de los elementos en el resultado? – augustss

+0

No, siempre que no haya repetición. –

+0

¿Qué tan grande necesita 'n' para ser? – dave4420

Respuesta

5

La forma más memoria ambiente se obtiene mediante la unión en el orden inverso en comparación con la secuencia,

foo 0 _ = [[]] 
foo k xs = [h:t | t <- foo (k-1) xs, h <- xs] 

Es más lento debido a la menor compartir, pero puesto que la memoria es su problema, tal vez es lo suficientemente bueno para usted.

+0

¡Genial! Tendré que investigar más por qué funciona, pero ciertamente sí. Lo modifiqué como 'foo (l: ls) = [h: t | t <- foo2 ls, h <- l] '(quién sabe si siempre necesitaré un cubo) y funciona también. ¡Gracias! –

+0

¿Por qué las listas son más eficientes que la notación para listas (que se usa en 'sequence')? Puedo ver en el informe Haskell2010 que ambos desugaron a 'concatMap'? – haskelline

+2

@brence: Vea la respuesta de Duncan Coutts a esta pregunta de reddit: [¿Por qué los guardias en la lista son más rápidos que en la notación do?] (Http://www.reddit.com/r/haskell/comments/oolyt/why_are_guards_in_the_list_comprehension_faster /) – danr

Cuestiones relacionadas