2009-02-20 22 views
6

Quindi, per esempio, dire che avevo una lista di numeri e volevo creare una lista che contenesse ciascun numero moltiplicato per 2 e 3. C'è un modo per fare qualcosa di simile a quanto segue, ma recuperare un singolo elenco di numeri invece di una lista di liste di numeri?Puoi creare più di un elemento di un elenco alla volta con una comprensione di lista in 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] 

risposta

13

è possibile utilizzare concat.

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

In alcuni casi simili concatMap può anche essere conveniente, anche se qui non cambia molto:

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

Per 'istanza Monad []', '(>> =) == flip concatMap' ... sembra che la risposta di Chris abbia sorvolato quella parte, ma questa risposta è un sottoinsieme di quello sopra. – ephemient

17

trovo che amplia l'elenco di comprensione rende più facile da leggere:

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

Potrebbe essere utile esaminare esattamente cosa fa e in che modo si riferisce ad altre soluzioni. Definiamo come una funzione:

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

Dopo un modo, questo desugars a

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

L'espressione concatMap (\m -> [m]) sta avvolgendo m in un elenco per appiattire immediatamente — è equivalente a map id .

confrontare questo a @ di FunctorSalad risposta:

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

Abbiamo ottimizzato via concatMap (\m -> [m]).

Ora @ risposta di Vili:

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

Questo desugars a:

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

Come nella prima soluzione di cui sopra, stiamo inutilmente creando una lista di liste che dobbiamo concat via.

Non penso che ci sia una soluzione che utilizza le list comprehensions, ma desugars su mult1. La mia intuizione è che i compilatori Haskell sono in genere abbastanza intelligenti da non importare (o, in alternativa, che gli inutili concat s sono economici a causa di una valutazione lenta (mentre sono letali in lingue volgari)).