2009-02-20 8 views
6

So, zum Beispiel sagen, ich hatte eine Liste von Zahlen und ich wollte eine Liste erstellen, die jede Zahl mit 2 und 3 multipliziert. Gibt es eine Möglichkeit, etwas wie das Folgende zu tun, aber eine einzelne Liste von Zahlen zurück anstelle einer Liste von Nummernlisten?Können Sie mehr als ein Element einer Liste gleichzeitig mit einem Listenverständnis in haskell erstellen?

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] 

Antwort

13

könnten Sie concat verwenden.

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

In einigen ähnlichen Fällen concatMap kann auch bequem sein, obwohl es hier nicht viel ändern:

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

Für 'Instanz Monad []', '(>> =) == Flip concatMap ... scheint es, dass Chris Antwort über diesen Teil beschönigt hat, aber diese Antwort ist eine Teilmenge des obigen. – ephemient

17

Ich finde, dass die Liste Verständnis erstreckt diese leichter zu lesen macht:

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

Es könnte hilfreich sein, genau zu untersuchen, was dies bewirkt und wie es sich auf andere Lösungen bezieht. Sagen wir es als eine Funktion definiert werden:

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

nach einer Mode, diese desugars zu

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

Der Ausdruck concatMap (\m -> [m]) wird m oben in einer Liste in der Reihenfolge Umwickeln sofort abzuflachen es — es entspricht map id .

Vergleichen Sie dies mit @ FunctorSalad Antwort:

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

Wir haben optimierte concatMap (\m -> [m]) entfernt.

Jetzt @ vili Antwort:

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

Diese desugars zu:

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

Wie in der ersten Lösung oben, werden wir unnötigerweise eine Liste von Listen erstellen, die wir zu concat entfernt haben.

Ich glaube nicht, dass es eine Lösung gibt, die List Comprehensions verwendet, aber entschuldigt zu mult1. Meine Intuition ist, dass Haskell-Compiler im Allgemeinen clever genug sind, dass dies keine Rolle spielt (oder alternativ dazu, dass unnötige concat s aufgrund der faulen Bewertung billig sind (während sie in eifrigen Sprachen tödlich sind)).