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)).
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