Первое, что нужно отметить, это то, что сам по себе этот код ничего не делает.Это просто набор математических выражений, и не имеет значения, насколько они круглые, пока мы не попытаемся извлечь из них некоторые значения.Как мы можем это сделать?
Мы могли бы сделать:
print $ take 1 primes1
Здесь нет проблем.Мы можем принять первое значение primes1, не обращая внимания ни на один из рекурсивного кода, он явно указан как 2. Как насчет:
print $ take 3 primes1
Давайте попробуем расширить primes1
, чтобы получить некоторые значения.Чтобы эти выражения были управляемыми, я теперь игнорирую части print
и take
, но помните, что мы делаем эту работу только из-за них.primes1
is:
primes1 = 2 : filter prime [3..]
У нас есть первое значение, и первым шагом к нашему второму является расширение фильтра.Если бы это был строгий язык, мы бы сначала попытались расширить [3 ..] и застрять.Возможное определение фильтра:
filter f (x:xs) = if f x then x : filter f xs else filter f xs
, что дает:
primes1 = 2 : if prime 3 then 3 : filter prime [4..] else filter prime [4..]
Наш следующий шаг должен выяснить, является ли prime 3
истинным или ложным, поэтому давайте расширим его, используянаши определения prime
, ldp
и ldpf
.
primes1 = 2 : if ldp 3 == 3 then 3 : filter prime [4..] else filter prime [4..]
primes1 = 2 : if ldpf primes1 3 == 3 then 3 : filter prime [4..] else filter prime [4..]
Теперь все становится интересным, primes1 ссылается на себя, а ldpf требуется первое значение для его вычисления.К счастью, мы можем легко получить первое значение.
primes1 = 2 : if ldpf (2 : tail primes) 3 == 3 then 3 : filter prime [4..] else filter prime [4..]
Теперь мы применяем защитные предложения в ldpf и находим 2^2 > 3
, поэтому ldpf (2 : tail primes) 3 = 3
.
primes1 = 2 : if 3 == 3 then 3 : filter prime [4..] else filter prime [4..]
primes1 = 2 : 3 : filter prime [4..]
Мы сейчасесть наше второе значение.Обратите внимание, что правая часть нашей оценки никогда не становилась особенно большой и что нам никогда не требовалось очень далеко следовать рекурсивному циклу.
primes1 = 2 : 3 : if prime 4 then 4 : filter prime [5..] else filter prime [5..]
primes1 = 2 : 3 : if ldp 4 == 4 then 4 : filter prime [5..] else filter prime [5..]
primes1 = 2 : 3 : if ldpf primes1 4 == 4 then 4 : filter prime [5..] else filter prime [5..]
primes1 = 2 : 3 : if ldpf (2 : tail primes1) 4 == 4 then 4 : filter prime [5..] else filter prime [5..]
Мы используем защитное предложение rem 4 2 == 0
, поэтому мы получаем 2 здесь.
primes1 = 2 : 3 : if 2 == 4 then 4 : filter prime [5..] else filter prime [5..]
primes1 = 2 : 3 : filter prime [5..]
primes1 = 2 : 3 : if prime 5 then 5 : filter prime [6..] else filter prime [6..]
primes1 = 2 : 3 : if ldp 5 == 5 then 5 : filter prime [6..] else filter prime [6..]
primes1 = 2 : 3 : if ldpf primes1 5 == 5 then 5 : filter prime [6..] else filter prime [6..]
primes1 = 2 : 3 : if ldpf (2 : tail primes) 5 == 5 then 5 : filter prime [6..] else filter prime [6..]
Нет защитных совпадений, поэтому мы повторяем:
primes1 = 2 : 3 : if ldpf (tail primes) 5 == 5 then 5 : filter prime [6..] else filter prime [6..]
primes1 = 2 : 3 : if ldpf (3 : tail (tail primes)) 5 == 5 then 5 : filter prime [6..] else filter prime [6..]
Теперь 3^2 > 5
, так что выражение равно 5.
primes1 = 2 : 3 : if 5 == 5 then 5 : filter prime [6..] else filter prime [6..]
primes1 = 2 : 3 : 5 : filter prime [6..]
Нам нужно только три значенияТаким образом, оценка может остановиться.
Итак, теперь, чтобы ответить на ваши вопросы.Ленивый список - это тот, который требует от нас только оценки того, что нам нужно, и 2 помогает, потому что он гарантирует, что когда мы достигнем рекурсивного шага, у нас всегда будет достаточно рассчитанных значений.(Представьте, что вы расширили бы это выражение, если бы мы не знали 2, мы бы очень быстро застряли в цикле.)