id:nobsun さんからコメントをもらった。ありがとうございます。
fib n = fibIter 1 1 n
where fibIter a b 0 = a
fibIter a b n = fibIter b (a+b) (n-1)
(※ちょっと変えました)
*Main> map fib [1..10] [1,2,3,5,8,13,21,34,55,89]
id:nobsun さんはこれ(↑)が id:pyletさんとこのループ版と同等だというのだけど,むしろ反復版(↓これ)と同等じゃないのかなぁ。
def fib3_iter(a, b, i, n):
if i == n:
return a
else:
return fib3_iter(b, a + b, i + 1, n)
def fib3(n):
return fib3_iter(1, 1, 0, n)
このPythonの関数(メソッド?)はカウンタに変数 i を使っているけど,重要なのは n と i の差 n-i なんだから n-i -> n に置き換えて n 自身をカウンタに使えば i をなくせる。内側のfib3_iterの引数は n-(i+1) = (n-i)-1 -> n-1 と置き換えられるから
def fib3_iter(a, b, n):
if n == 0:
return a
else:
return fib3_iter(b, a + b, n - 1)
def fib3(n):
return fib3_iter(1, 1, n)
これならまさしく上のHaskellと同じだ。
あー,でも,そうか。既知の第0項と第1項をもとにして第n項まで頭から順に計算していく,という点ではどっちも同等だといえるのか。
いや,まて。再帰してる反復版ではスタックを積まなきゃいけないけどループ版ではいらないはずだな。
いやいや,遅延評価するからいらないのか?……違うか?
だめだ。わかんなくなった。