7

Я совершенно новый для Haskell, и я пытаюсь обернуть вокруг себя то, как работает ленивое выражение последовательностей Фибоначчи.Haskell Fibonacci Пояснение

Я знаю, что это было задано раньше, но ни один из ответов не затронул проблему, которую я испытываю, визуализируя результат.

код является каноническим с помощью zipWith

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

Я понимаю следующее:

  1. zipWith буквально молниеносно два списка вместе
  2. tail грейферов все, кроме первого элемента списка
  3. Haskell ссылается на «вычисленные» данные как thunks.

В моем понимании, это первый добавляет [0,1,<thunk>] и [1,<thunk>] использованием zipWith (+) дать [1,<thunk>]. Так что теперь у вас есть

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

Много ссылок я Гугле потом приступил к «визуализировать» строку выше, как

fibs = 0 : 1 : 1 : zipWith (+) [1,1,<thunk>] ([1,<thunk>]). 

Мой вопрос заключается в следующем:

ПочемуfibsКомпонент в строке выше соответствует только[1,1,<thunk>]вместо[0,1,1,<thunk>]?

Не должен fibs содержать весь список плюс <thunk>?

+0

хороший способ понять такие определения является [название промежуточных значений] (http://stackoverflow.com/a/20978114/849891), которые приходят в существование, как мы постепенно к ним доступ (например, в 'взять 3 fibs'). Таким образом, нет никакой путаницы между тем, что один и тот же доступ к данным дважды (через одно и то же имя) или две равные части данных (каждая из которых имеет собственное имя). –

ответ

11

Этот промежуточный шаг является неправильным, потому что zipWith уже обработал первую пару пунктов:

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

Напомним, что zipWith делает в общем случае:

zipWith f (x:xs) (y:ys) = (f x y) : zipWith f xs ys 

Если применить определение непосредственно вам получить это расширение:

fibs = 0 : 1 : zipWith (+) fibs (tail fibs)    # fibs=[0,1,...] 
    = 0 : 1 : zipWith (+) [0,1,...] (tail [0,1,...])  # tail fibs=[1,...] 
    = 0 : 1 : zipWith (+) [0,1,...] [1,...]    # apply zipWith 
    = 0 : 1 : (0+1 : zipWith (+) [1,0+1,...] [0+1,...]) 
    = 0 : 1 : 1 : zipWith (+) [1,1,...] [1,...]   # apply zipWith 
    = 0 : 1 : 1 : (1+1 : zipWith (+) [1,1+1,...] [1+1,...]) 
    = 0 : 1 : 1 : 2 : zipWith (+) [1,2,...] [2,...]  # apply zipWith 
    = 0 : 1 : 1 : 2 : (1+2 : zipWith (+) [2,1+2,...] [1+2,...]) 
    = 0 : 1 : 1 : 2 : 3 : zipWith (+) [2,3...] [3,...] # apply zipWith 
    : 
+0

+1 Спасибо за объяснение, @Joni. Я думаю, что сейчас я начинаю понимать это, но у меня еще есть еще один вопрос, какие ссылки на мой оригинальный вопрос. В вашей четвертой строке, где у вас есть fibs = 0: 1: 1: zipWith (+) [1,1, ...] [1, ...], почему список после zipWith (+) имеет только [1,1, ...] вместо всего списка? – MikamiHero

+1

zipWith берет пару элементов, применяет к ним функцию и рекурсирует на * хвосты * входных списков .. может быть, мне следует расширить, что дальше – Joni

+0

, если вы не возражаете расширить это, я был бы очень признателен ! Я очень новичок в Haskell, и у меня голова в петле (каламбур не предназначен). – MikamiHero

1

Как визуализировать wha продолжается.

1 1 2 3 5 8 13 <----fibs 
    1 2 3 5 8 13  <----The tail of fibs 
+________________ <----zipWith (+) function 
    2 3 5 8 13 21  <----New fibs. 13 drops out --nothing to zip with 

finally, add [1, 1] to beginning 
1, 1, 2, 3, 5, 8, 13, 21 
Смежные вопросы