2009-02-20 20 views
6

Załóżmy na przykład, że mam listę numerów i chciałem utworzyć listę, która zawierałaby każdy numer pomnożony przez 2 i 3. Czy istnieje sposób na zrobienie czegoś takiego, jak poniżej, ale wróć do pojedynczej listy liczb zamiast listy list liczb?Czy możesz utworzyć więcej niż jeden element listy na raz ze zrozumieniem listy w 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] 

Odpowiedz

13

można użyć konkat.

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

W niektórych podobnych przypadkach concatMap może być również wygodne, chociaż tutaj nie zmienia wiele,

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

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

17

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