В Haskell, в чем разница между использованием takeWhile или «обычным» неравенством в понимании этого списка?

Я пытаюсь выучить меня на Haskell (для хорошего блага), и одна из многих разных вещей, которые я делаю, - это попытаться решить некоторые проблемы Project Euler, пока я иду, чтобы проверить свои способности.

Выполняя некоторые задачи, основанные на Фибоначчи, я наткнулся на и начал играть с рекурсивной версией бесконечного списка последовательности Фибоначчи:

fibs = 1 : 2 : zipWith (+) fibs (tail fibs)

Для одной из задач PE мне нужно было извлечь подпоследовательность четных чисел Фибоначчи меньше, чем 4 000 000. Я решил сделать это с пониманием списка, и, играя с кодом, я наткнулся на то, чего не совсем понимаю; Я предполагаю, что это мое слабое понимание ленивой схемы оценки Haskell, которая усложняет ситуацию.

Следующее понимание работает просто отлично:

[x | x <- takeWhile (<= 4000000) fibs, even x]

Следующее понимание вращается навсегда; поэтому я прошел и вернул вывод в stdout, и пока он останавливается в правильном месте, кажется, что он продолжает вычислять рекурсивно определенный список навсегда, не заканчивая после достижения ограниченного значения; указывает на то, что последний элемент в списке печатается через запятую, но никаких дополнительных элементов списка или закрывающей квадратной скобки нет:

[x | x <- fibs, x <= 4000000, even x]

Так в чем же секретный соус, используемый различными функциями, которые хорошо работают с бесконечными списками?

Ответы на вопрос(1)

Ваш ответ на вопрос