pierrが答えたように、を使用する必要がありますfoldl'
。詳細については:
foldl'
フォールドステップに渡す前に、その「左側」を計算します。
foldr
フォールドステップに右側の値の「サンク」を与えます。この「サンク」は、必要に応じて計算されます。
foldr
で合計を作成し、それがどのように評価されるかを見てみましょう。
foldr (+) 0 [1..3]
1 + foldr (+) 0 [2..3]
1 + 2 + foldr (+) 0 [3]
1 + 2 + 3 + foldl (+) 0 [] -- this is a big thunk..
1 + 2 + 3 + 0
1 + 2 + 3
1 + 5
6
そしてfoldl'
: (タグは SO ではうまく表示されないため、コードでは省略されています)
foldl (+) 0 [1..3]
-- seq is a "strictness hint".
-- here it means that x is calculated before the foldl
x `seq` foldl (+) x [2..3] where x = 0+1
foldl (+) 1 [2..3]
x `seq` foldl (+) x [3] where x = 1+2
foldl (+) 3 [3]
x `seq` foldl (+) x [] where x = 3+3
foldl (+) 6 []
6
foldr
漏れない、の良い用途に。「ステップ」は次のいずれかでなければなりません。
- 「右側」に依存しない結果を返し、それを無視するか、遅延構造に含めます
- 右側をそのまま返す
良いfoldr
使用例:
-- in map, the step returns the structure head
-- without evaluating the "right-side"
map f = foldr ((:) . f) []
filter f =
foldr step []
where
step x rest
| f x = x : rest -- returns structure head
| otherwise = rest -- returns right-side as is
any f =
foldr step False
where
-- can use "step x rest = f x || rest". it is the same.
-- version below used for verbosity
step x rest
| f x = True -- ignore right-side
| otherwise = rest -- returns right-side as is