6

Learn you a Haskellで読んだことがありますが、Haskellのリスト内包表記はモナド結合または (実質的には同じ) do 表記として書き直すことができます。

ただし、次のコードを書き直そうとすると (指定されたリストの 1 つから各要素を持つすべての可能なリストを生成します):

c :: [[a]] -> [[a]]
c []     = [[]]
c (x:xs) = [a:b | a <- x, b <- c xs]

そのような方法で:

d :: [[a]] -> [[a]]
d []     = [[]]
d (x:xs) = do
              a <- x
              b <- d xs
              return a:b

次のエラーが表示されます。

Couldn't match type `a' with [a]
    `a' is a rigid type variable bound by
        the type signature for d :: [[a]] -> [[a]] 
Expected type: [[a]]
  Actual type: [a] 
In the second argument of `(:)', namely `b' 
In a stmt of a 'do' block: return a : b

の最後の行doを this:に変更するreturn a:[b]と、エラーは発生しませんが、結果は明らかに正しくありません:

ghci> c [[1, 2], [3, 4]] 
[[1,3],[1,4],[2,3],[2,4]]

ghci> d [[1, 2], [3, 4]]
[[1],[3],[1],[],[1],[4],[1],[],[2],[3],[2],[],[2],[4],[2],[]]

質問は次のとおりです。

  1. このリスト内包表記を書き直すにはどうすればよいですか?
  2. リスト内包表記とdo記法は交換可能ですか?一般的にどのように交換できますか?
4

2 に答える 2