22

Haskellにはリスト用の2つの左折り関数があります:foldlと「厳密な」バージョン、foldl'。非厳密の問題はfoldl、サンクの塔を構築することです。

    foldl (+) 0 [1..5]
--> ((((0 + 1) + 2) + 3) + 4) + 5
--> 15

これはメモリを浪費し、リストに項目が多すぎるとスタックオーバーフローを引き起こす可能性があります。 foldl'一方、すべてのアイテムにアキュムレータを強制します。

ただし、私が知る限り、意味的foldl'にはと同等です。通常の形式で評価するには、ある時点でアキュムレータを強制する必要があります。ヘッドノーマルフォームが必要なければ、そもそも評価していません。foldlfoldl (+) 0 [1..5]foldl (+) 0 [1..5]

foldlそれ以上の振る舞いをしたいという説得力のある理由はありfoldl'ますか?

4

2 に答える 2

26

foldlfoldl'意味的に同等ではありません。些細な反例:

Prelude Data.List> foldl (\x y -> y) 0 [undefined, 1]
1
Prelude Data.List> foldl' (\x y -> y) 0 [undefined, 1]
*** Exception: Prelude.undefined

ただし、実際には、通常、foldl'前述の理由から厳密なものが必要です。

于 2011-11-23T00:37:37.573 に答える
14

ハンマーの例のように、同じ結果が得られる場合foldlと得られない場合は、目的の結果に従って決定を下す必要があります。foldl'それとは別に、folded関数がコンストラクターである場合(コンストラクターを適用するとWHNFに値が作成されるため、WHNFに再度強制する意味はありません)ではfoldlなく、WHNFを強制しても何も得られない場合に使用します。これらの例外的なケースとは別に、選択する方法があります。foldl'foldl (.) id functionsfoldl'

于 2011-11-23T00:46:50.130 に答える