2009-02-20 25 views
6

Entonces, por ejemplo, supongamos que tengo una lista de números y quiero crear una lista que contenga cada número multiplicado por 2 y 3. ¿Hay alguna manera de hacer algo como lo siguiente, pero obtener una lista única de números en lugar de una lista de listas de números?¿Puedes crear más de un elemento de una lista a la vez con una lista de comprensión en haskell?

mult_nums = [ [(n*2),(n*3)] | n <- [1..5]] 
-- this returns [[2,3],[4,6],[6,9],[8,12],[10,15]] 
-- but we want [2,3,4,6,6,9,8,12,10,15] 

Respuesta

13

se puede usar concat.

concat [ [(n*2),(n*3)] | n <- [1..5]] 
output: [2,3,4,6,6,9,8,12,10,15] 
5

En algunos casos similares concatMap también puede ser conveniente, aunque aquí no cambia mucho:

concatMap (\n -> [n*2,n*3]) [1..5]
+0

Para 'instancia Monad []', '(>> =) == voltear concatMap' ... parece que la respuesta de Chris pasó por alto esa parte, pero esta respuesta es un subconjunto de la anterior. – ephemient

17

encuentro que se amplía la lista de comprensión hace esto más fácil de leer:

[ m | n <- [1..5], m <- [2*n,3*n] ] 

Puede ser útil examinar exactamente qué hace esto y cómo se relaciona con otras soluciones. Vamos a definir como una función:

mult lst = [ m | n <- lst, m <- [2*n,3*n] ] 

Después de una moda, este desugars a

mult' lst = 
    concatMap (\n -> concatMap (\m -> [m]) [2*n,3*n]) lst 

La expresión concatMap (\m -> [m]) está terminando m en una lista con el fin de aplanar inmediatamente — es equivalente a map id .

comparar esto con la respuesta de @ FunctorSalad:

mult1 lst = concatMap (\n -> [n*2,n*3]) lst 

Hemos optimizado de distancia concatMap (\m -> [m]).

Ahora @ respuesta de Vili:

mult2 lst = concat [ [(n*2),(n*3)] | n <- lst] 

Este desugars a:

mult2' lst = concat (concatMap (\n -> [[2*n,3*n]]) lst) 

Al igual que en la primera solución anterior, estamos creando innecesariamente una lista de listas que tenemos que concat de distancia.

No creo que haya una solución que use listas de comprensión, pero desácidos a mult1. Mi intuición es que los compiladores de Haskell son generalmente lo suficientemente inteligentes como para que esto no importara (o, alternativamente, que los concat s innecesarios son baratos debido a la evaluación perezosa (mientras que son letales en los idiomas ansiosos)).

Cuestiones relacionadas