2

それで、私はここで質問を見て、問題のかなり醜い解決策を構築しました。それをきれいにしようとしている間、私はリスト内包表記とリストモナドを調査し始めました。私がやろうと思ったのは、リストモナドを使用して桁ごとのカウンターを実装することでした。数字の入力シーケンスが与えられた場合、[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

4 に答える 4

8
count = sequence . map (enumFromTo 0)

はい、それは本当にそれと同じくらい簡単です。試してみる :)

于 2009-12-06T19:09:05.770 に答える
8

さらに短い

count = mapM (enumFromTo 0)
于 2009-12-07T02:39:35.183 に答える
3

完全を期すために、ロジックをリスト内包表記として表現することもできます。これは、単純な関数にリストモナドを使用するためのおそらく最良の方法です。

count (x:xs) = [ (y:ys) | y <- [0..x], ys <- count xs ]
于 2009-12-06T19:12:29.193 に答える
2

まず、引数としてシングルトンリストのベースケースが必要です。これを試して:

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]
于 2009-12-06T18:27:13.793 に答える