12

Haskell の学習を始めたばかりで (文字通り、今夜!)、リスト内包表記のロジック、より具体的には<-演算子を理解するのに少し苦労しています。Learn You Some Haskellの小さな例は、長さが 10 未満のすべてのタプルを検索します。

ghci> let triangles = [ (a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10] ]

私の最初の理解では、これらはすべて一緒に増加するということでしたが、出力を見た後、これらのリストの増加方法を本当に理解していません。私を納得させるように思われる別の例は次のとおりです。

ghci> let rightTriangles = [ (a,b,c) | c <- [1..10], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2]

これらについて少し説明していただければ幸いです。私の Haskell の知性の欠如をご辛抱いただきありがとうございます。

4

3 に答える 3

20

["list of"、|"for"、<-"in"、,"and" と読みます。

列挙はネストされた方法で行われます。[ (a,b,c) | c <- [1..10], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2]本当に

for c from 1 to 10 step 1:
   for b from 1 to c step 1:
      for a from 1 to b step 1:
          if (a^2 + b^2 == c^2):
             emit (a,b,c)

ただしHaskellでは、上記は次の翻訳によって達成されます

[1..10] >>= (\c->               -- (a function of 'c', producing ...
  [1..c]  >>= (\b->               -- (a function of 'b', producing ...
    [1..b]  >>= (\a->               -- (a function of 'a', producing ...
      if a^2+b^2==c^2 then [(a,b,c)] else []
      -- or: [(a,b,c) | a^2+b^2==c^2]
      )))

ここでネストされた構造を実際に見ることができます。(>>=)神秘的なものでもありません。>>=正式名称は「バインド」ですが、「フィードイン」または「プッシュスルー」と読みます。(リストの場合)次のように定義されます

(xs >>= f) = concatMap f xs = concat (map f xs)

fmaphere は、 の各要素に対してxs順番に(によって) 呼び出されます。と組み合わせることができるように、リストを生成する必要がありますconcat。空のリスト[]concat(たとえばconcat [[1], [], [3]] == [1,3])で削除されるため、テストに合格しないすべての要素は最終出力から削除されます。


完全な翻訳については、Haskell 98 レポートのセクション 3.11, List Comprehensionsを参照してください。一般に、リスト内包表記には、変数名だけでなく、パターンを含めることができます。理解

[e | pat <- ls, ...]  

として翻訳されます

ls >>= (\x -> case x of pat -> [e | ...] ;
                        _   -> [] )

wherepatは何らかのパターンで、xは新しい変数です。パターンの不一致がある場合、(実行時エラーの代わりに) 空のリストが生成され、その要素xlsスキップされます。[x | Just x <- ls, even x]これは、すべてのNothingslsが静かに無視される場合など、追加のパターンベースのフィルタリングに役立ちます。

于 2013-05-29T03:59:21.533 に答える
4

[ (a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10] ](a,b,c) のすべての組み合わせ (a は [1..10]、b は [1..10]、c は [1..10]) を意味します。

(1,1,1) (2,2,2) 種類が必要な場合は、zip:zip [1..10] [1..10]または 3 つのリストを使用する必要があります。zip3 [1..10] [1..10] [1..10]

于 2013-05-29T03:50:10.663 に答える
1

私は、リスト内包表記の構文を、Haskellが言語でSet-builder 表記法を取得しようとしていると考えています。'{' ではなく '[' を使用し、'ε' ではなく '<-' を使用します。リスト内包表記の構文は、任意のモナドに一般化することさえできます。

于 2013-06-07T07:17:22.930 に答える