Мне интересно узнать о производительности во время выполнения бесконечного списка ниже:
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 делает некоторое кэширование для предотвращения множественных оценок здесь?