0

リスト内包表記についてはある程度理解しています。私は次の表現を理解しています:

[x * x | x <- [1..10]]
should output [1,4,9,16,25,36,49,64,81,100]

そして、その式の効果は次と同じです。

map power [1..10]
power x = x * x

ここで、次の関数の他の方法 (上記と同様) を見つける必要があります。

[(x,y+z) | x <- [1..10], y <- [1..x], z <- [1..y]]

エラーなしで自分で理解することはできません、助けてください

4

3 に答える 3

8

Haskell Reportは、リスト内包表記をどのように変換するかを教えてくれます:

[ e | True ]         = [e]
[ e | q ]            = [ e | q, True ]
[ e | b, Q ]         = if b then [ e | Q ] else []
[ e | p <- l, Q ]    = let ok p = [ e | Q ]
                           ok _ = []
                       in concatMap ok l
[ e | let decls, Q ] = let decls in [ e | Q ]

リスト内包表記は反駁できないパターン (つまり、決して失敗しないパターン) のみを使用するため、上記の 4 番目の節はいくらか単純化されています。

[ e | p <- l, Q ]    = concatMap (\p -> [ e | Q ]) l

簡潔にするためにこのバージョンを使用しますが、真の導出ではレポートの定義を使用する必要があります。(宿題: 実際の翻訳を試してみて、最終的に「同じもの」が得られることを確認してください。) 試してみましょう。

  [(x,y+z) | x <- [1..10], y <- [1..x], z <- [1..y]]
= concatMap (\x -> [(x,y+z) | y <- [1..x], z <- [1..y]] [1..10]
= concatMap (\x -> concatMap (\y -> [(x,y+z) | z <- [1..y]]) [1..x]) [1..10]
= concatMap (\x -> concatMap (\y -> [(x,y+z) | z <- [1..y], True]) [1..x]) [1..10]
= concatMap (\x -> concatMap (\y -> concatMap (\z -> [(x,y+z) | True]) [1..y]) [1..x]) [1..10]
= concatMap (\x -> concatMap (\y -> concatMap (\z -> [(x,y+z)]) [1..y]) [1..x]) [1..10]

そして、ついにリスト内包表記のないバージョンにたどり着きました。

concatMapモナドに慣れている場合は、リストの(>>=)関数の反転バージョンであることを観察することで、この式の動作についての洞察を得ることができます。また、[e]リストの のようなものreturn eです。したがって、モナド演算子で書き直すと、次のようになります。

= [1..10] >>= \x ->
  [1..x]  >>= \y ->
  [1..y]  >>= \z ->
  return (x,y+z)
于 2011-10-19T13:12:41.437 に答える
5
[(x,y+z) | x <- [1..10], y <- [1..x], z <- [1..y]]

と同じです

concatMap
    (\x -> [(x,y+z) | y <- [1..x], z <- [1..y]])
    [1..10]

同様に、リスト内包表記から変数yと変数を抽出できます。z(ただし、左から右に順番に実行する必要があります。つまり、y次でz最後です。)

concatMapPrelude で定義された関数です。

concatMap :: (a -> [b]) -> [a] -> [b]
concatMap f = concat . map f
于 2011-10-19T10:28:25.897 に答える
3

doこれを-notationに変換できます:

foo = do x <- [1..10]
         y <- [1..x]
         z <- [1..y]
         return (x, y+z)

リストはモナドであるため、これは機能します。-do表記自体は、モナド計算の構文糖衣にすぎません。脱糖規則 ( 「do ブロックの脱糖」で説明) に従うと、次のようになります

[1..10] >>= (\x -> [1..x] >>= (\y -> [1..y] >>= (\z -> [(x,y+z)])))

演算子>>=は で定義されており、リストの反転された引数を持つ とControl.Monad同等です。リストの場合のみです。concatMapreturn t[t]

于 2011-10-19T10:48:24.680 に答える