以下のような無限リストの実行時のパフォーマンスに興味があります。
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
これにより、フィボナッチ数列の無限リストが作成されます。
私の質問は、次のことを行う場合です。
takeWhile (<5) fibs
fibs
はリスト内の各用語を何回評価しますか? takeWhile
リスト内の各項目の述語関数をチェックするため、リストfibs
は各項を複数回評価するようです。最初の 2 タームは無料で提供されます。3 番目の要素takeWhile
を評価
する場合は、次のようになります。(<5)
1 : 1 : zipWith (+) [(1, 1), (1)] => 1 : 1 : 3
ここで、一度4 番目の要素takeWhile
を評価したい場合(<5)
: の再帰的な性質によりfibs
、次のようにリストが再度構築されます。
1 : 1 : zipWith (+) [(1, 2), (2, 3)] => 1 : 1 : 3 : 5
4 番目の要素の値を評価するには、3 番目の要素を再度計算する必要があるようです。さらに、述語 intakeWhile
が大きい場合は、関数がリスト内の前の各要素を複数回評価しているため、関数が必要なより多くの作業を行っていることを示します。ここでの私の分析は正しいですか、それともHaskellはここで複数の評価を防ぐためにキャッシュを行っていますか?