Одним из преимуществ функционального программирования является то, что вы можете оценить выражение вручную, как будто это математическая задача:
fibs = 0 : 1 : [ a + b | (a, b) <- zip fibs (tail fibs)]
= 0 : 1 : [ a + b | (a, b) <- zip [0, 1, ??] (tail [0, 1, ??])]
Здесь ??
- это часть, которая еще не была оценена. Мы заполним его по мере продвижения.
= 0 : 1 : [ a + b | (a, b) <- zip [0, 1, ??] [1, ??])]
= 0 : 1 : [ a + b | (a, b) <- (0, 1) : zip [1, ??] [??]]
Обратите внимание, что я отказываюсь от оценки zip
, так как ее определение здесь не приводится, а детали на самом деле не имеют отношения к текущему вопросу. Это обозначение, которое я буду использовать, чтобы показать, что каждая пара чисел создана zip
и используется для понимания списка.
= 0 : 1 : 0+1 : [ a + b | (a, b) <- zip [1, ??] [??]]
= 0 : 1 : 1 : [ a + b | (a, b) <- zip [1, ??] [??]]
Теперь мы знаем, что следующим элементом в ??
является 1
:
= 0 : 1 : 1 : [ a + b | (a, b) <- zip [1, 1, ??] [1, ??]]
= 0 : 1 : 1 : [ a + b | (a, b) <- (1, 1) : zip [1, ??] [??]]
= 0 : 1 : 1 : 1+1 : [ a + b | (a, b) <- zip [1, ??] [??]]
= 0 : 1 : 1 : 2 : [ a + b | (a, b) <- zip [1, ??] [??]]
А следующим элементом является 2:
= 0 : 1 : 1 : 2 : [ a + b | (a, b) <- zip [1, 2, ??] [2, ??]]
Сполосните и повторите.