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