Uważam, że rozszerzenie listy ze zrozumieniem sprawia, że to łatwiejsze do odczytania:
[ m | n <- [1..5], m <- [2*n,3*n] ]
Pomocne może okazać się zbadanie, co dokładnie robi i jak odnosi się do innych rozwiązań. Załóżmy zdefiniować go jako funkcję:
mult lst = [ m | n <- lst, m <- [2*n,3*n] ]
Po modzie, to desugars do
mult' lst =
concatMap (\n -> concatMap (\m -> [m]) [2*n,3*n]) lst
Wyrażenie concatMap (\m -> [m])
jest owijanie m
się na liście, aby natychmiast spłaszczyć to — jest to równoważne map id
.
Porównaj to do użytkownika @ FunctorSalad odpowiedź:
mult1 lst = concatMap (\n -> [n*2,n*3]) lst
Mamy zoptymalizowane dala concatMap (\m -> [m])
.
Teraz @ Vili na odpowiedź:
mult2 lst = concat [ [(n*2),(n*3)] | n <- lst]
Ten desugars do:
mult2' lst = concat (concatMap (\n -> [[2*n,3*n]]) lst)
jak w pierwszym roztworze powyżej, jesteśmy niepotrzebnie Tworzenie listy list, że mamy do concat
dalej.
Nie sądzę, że istnieje rozwiązanie, które wykorzystuje wyliczenia listy, ale wygasza do mult1
. Moją intuicją jest to, że kompilatory Haskell są na ogół wystarczająco sprytne, że nie ma to znaczenia (lub, alternatywnie, niepotrzebne concat
s są tanie ze względu na leniwą ocenę (podczas gdy są one zabójcze w gorliwych językach)).
Dla 'instance Monad []', '(>> =) == flip concatMap' ... wydaje się, że odpowiedź Chrisa nad tym fragmensem była krótka, ale ta odpowiedź jest podzbiorem powyższej. – ephemient