Понимание списка в Haskell - PullRequest
7 голосов
/ 12 мая 2011

Я использовал следующий код для получения всех комбинаций заранее определенного количества чисел:

getList x = [ [a,b,c] | a <- [1..x], b <- [1..x], c <- [1..x]]

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

getList x = [ [a,b,c,d] | a <- [1..x], b <- [1..x], c <- [1..x], d <- [1..x]]

Это не обязательно должно быть понимание списка. Спасибо за любую помощь.

Ответы [ 2 ]

17 голосов
/ 12 мая 2011

Я полагаю, что вы хотели бы использовать функцию replicateM в Control.Monad.

Монада списка основана на «попытке всех возможных комбинаций», и обычный replicate создает список, повторяя элемент несколько раз. Таким образом, результатом replicateM является, учитывая некоторый список возможных значений, список всех возможных способов выбора элемента из этого списка несколько раз.

Например:

> replicateM 2 [0, 1]
[[0,0],[0,1],[1,0],[1,1]]
> replicateM 3 [0, 1]
[[0,0,0],[0,0,1],[0,1,0],[0,1,1],[1,0,0],[1,0,1],[1,1,0],[1,1,1]]

Таким образом, чтобы распространить свою функцию на произвольные повторения, вы должны использовать что-то вроде:

getListN n x = replicateM n [1..x]

... где ваш исходный getList будет эквивалентен getListN 3.

3 голосов
/ 13 мая 2011

В случае, если кому-то нравится не-монадическое решение для понимания внутренней работы (хотя, решение через replicateM великолепно!):

getListN n = foldl (\ass bs -> [ b:as | b <- bs, as <- ass]) [[]] . replicate n

По сути, эта реализация через foldlработает точно так же, как и replacatM -раствор.

...