Можете ли вы создать более одного элемента списка одновременно с пониманием списка в haskell? - PullRequest
6 голосов
/ 20 февраля 2009

Так, например, скажем, у меня был список чисел, и я хотел создать список, который содержал бы каждое число, умноженное на 2 и 3. Есть ли способ сделать что-то вроде следующего, но получить один список цифры вместо списка списков номеров?

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]

Ответы [ 3 ]

17 голосов
/ 20 февраля 2009

Я считаю, что расширение понимания списка облегчает чтение:

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

Может быть полезно изучить, что именно это делает и как это связано с другими решениями. Давайте определим это как функцию:

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

После моды, это Desugars до

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

Выражение concatMap (\m -> [m]) помещает m в список для немедленного выравнивания его - это эквивалентно map id.

Сравните это с ответом @ FunctorSalad:

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

Мы оптимизировали прочь concatMap (\m -> [m]).

Теперь @ Вили ответ:

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

Это desugars к:

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

Как и в первом решении, приведенном выше, мы излишне создаем список списков, которые мы должны concat удалить.

Я не думаю, что есть решение, которое использует списки, но десугары для mult1. Моя интуиция заключается в том, что компиляторы Haskell, как правило, достаточно умны, чтобы это не имело значения (или, наоборот, ненужные concat являются дешевыми из-за ленивых вычислений (в то время как они смертельны для активных языков)).

13 голосов
/ 20 февраля 2009

вы можете использовать concat.

concat [ [(n*2),(n*3)] | n <- [1..5]] 
output: [2,3,4,6,6,9,8,12,10,15]
5 голосов
/ 20 февраля 2009

В некоторых подобных случаях concatMap также может быть удобен, хотя здесь он не сильно меняется:

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