Haskell 使用列表monad实现每位数计数器

Haskell 使用列表monad实现每位数计数器,haskell,list-comprehension,monads,Haskell,List Comprehension,Monads,因此,我在研究这个问题,并为这个问题建立了一个相当丑陋的解决方案。在试图清理它的时候,我开始研究列表理解和列表单子。我决定使用列表monad实现一个每位数计数器。给定一个数字输入序列,[1,2],我想生成一个输出序列,看起来像: [ [ 0, 0], [ 0, 1 ], [ 0, 2 ], [ 1, 0 ], [ 1, 1 ], [ 1, 2 ] ] 也就是说,我将迭代该范围内列表中所有元素的所有可能值 haskell.org说: 绑定函数应用于输入列表中的所有可能值,并将

因此,我在研究这个问题,并为这个问题建立了一个相当丑陋的解决方案。在试图清理它的时候,我开始研究列表理解和列表单子。我决定使用列表monad实现一个每位数计数器。给定一个数字输入序列,
[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)
计数::[Integer]->[[Integer]]
计数[]=[]
计数(x:xs)=
--获取剩余数字的所有可能序列
让
remDigits::[[Integer]]
remDigits=计数xs
在里面
--拉出剩余数字的可能顺序

do nextDigits首先,您需要单例列表的基本情况作为参数。试试这个:

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]
计数::[Integer]->[[Integer]]
计数[]=[]
计数[n]=map(\x->[x])[0..n]
计数(x:xs)=
多愁善感

是的,就这么简单。试试看:)

为了完整起见,您还可以将逻辑表示为列表理解,这可能是将列表单子用于简单函数的最佳方式:

count (x:xs) = [ (y:ys) | y <- [0..x], ys <- count xs ]
count(x:xs)=[(y:ys)| y甚至更短

count = mapM (enumFromTo 0)

产生的结果与OP指定的结果不同!剩余的错误与我使用单子的顺序有关。如果您只需将基本大小写更改为
count[]=[[],我应该有y
,这段代码很有效。实际上,这正是我想要的答案……我发现我的问题是,在基本情况下,单子列表中没有解决方案,因此没有任何东西可供构建。CBFraser下面的答案解决了这一问题,但你的解决方案更接近我最初的想法。哦,不确定我错过了
sequence+map
mapM
的机械翻译,但是明显的改进是+1:D
count = mapM (enumFromTo 0)