реализация счетчика на одну цифру с использованием монады списка - PullRequest
2 голосов
/ 06 декабря 2009

Итак, я смотрел на вопрос здесь и выстроил довольно уродливое решение проблемы. Пытаясь очистить его, я начал исследовать списки и списочную монаду. Я решил внедрить счетчик на одну цифру, используя монаду списка. Учитывая входную последовательность цифр, [1, 2], я хотел сгенерировать выходную последовательность, которая выглядела бы примерно так:

[ [ 0, 0],
  [ 0, 1 ],
  [ 0, 2 ],
  [ 1, 0 ],
  [ 1, 1 ],
  [ 1, 2 ] ]

То есть я бы перебрал все возможные значения всех элементов в списке в этом диапазоне.

haskell.org список монад документации говорит:

Связанная функция применяется ко всем возможным значениям во входном списке, и результирующие списки объединяются для получения списка всех возможных результатов.

Отлично! Выглядит идеально ... Вот код, который я написал, чтобы получить решение:

count :: [Integer] -> [[Integer]]
count [] = []
count (x:xs) =
  -- get all possible sequences for the remaining digits
  let
    remDigits :: [[Integer]]
    remDigits = count xs
  in
  -- pull out a possible sequence for the remaining digits
  do nextDigits <- remDigits
     -- pull out all possible values for the current digit
     y <- [0..x]
     -- record that "current digit" : "remaining digits" is
     -- a valid output.
     return (y:nextDigits)

Но при вызове count с чем-либо получается пустой список, и я не знаю почему. Чего мне не хватает?

Ответы [ 4 ]

8 голосов
/ 07 декабря 2009

еще короче

count = mapM (enumFromTo 0)
8 голосов
/ 06 декабря 2009
count = sequence . map (enumFromTo 0)

Да, это действительно так просто. Попробуй :))

3 голосов
/ 06 декабря 2009

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

count (x:xs) = [ (y:ys) | y <- [0..x], ys <- count xs ]
2 голосов
/ 06 декабря 2009

Во-первых, вам нужен базовый регистр для одноэлементного списка в качестве аргумента. Попробуйте это:

count :: [Integer] -> [[Integer]]
count [] = []
count [n] = map (\x -> [x]) [0..n]
count (x:xs) =
     do y <- [0..x]
        nextDigits <- count xs
        return (y:nextDigits)

 main = do
   print $ count [1]
   print $ count [1,2]
...