Мне интересно узнать о производительности во время выполнения бесконечного списка ниже:
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
Это создаст бесконечный список последовательности фибоначчи.
Мой вопрос в том, что если я сделаю следующее:
takeWhile (<5) fibs
сколько раз fibs оценивать каждый термин в списке? Кажется
что, поскольку takeWhile проверяет функцию предиката для каждого элемента в
список, список fibs будет оценивать каждый термин несколько раз.
первые 2 условия даются бесплатно. Когда takeWhile хочет оценить
(<5) на 3-м элементе, мы получим:
1 : 1 : zipWith (+) [(1, 1), (1)] => 1 : 1 : 3
Теперь, когда takeWhile хочет оценить (<5) для 4-го элемента:
рекурсивный характер fibs будет строить список снова, как
следующее:
1 : 1 : zipWith (+) [(1, 2), (2, 3)] => 1 : 1 : 3 : 5
Казалось бы, третий элемент нужно снова вычислить, когда мы
хотите оценить значение 4-го элемента. Кроме того, если
предикат в takeWhile велик, это указывает на то, что функция
делать больше работы, которая необходима, поскольку она оценивает каждый предыдущий
элемент в списке несколько раз. Является ли мой анализ здесь правильным или
Haskell делает некоторое кэширование для предотвращения множественных оценок здесь?

