フィボナッチ数列

折角遅延評価とかしてくれるので,フィボナッチしないと勿体ない.ついでに,簡単な制御構造の勉強(条件分岐)を.


まずは簡単なトコロから.

fib :: Integer -> Integer
fib 1 = 1
fib 2 = 1
fib n = fib (n - 1) + fib (n - 2)

hugsでの実行結果です.

Main> map fib [1..20]
[1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765]

いかにHaskellと言えど,hugsインタプリタはショボイのか,実行結果がズルズルと表示される様が見れました.流石にmainを書いてコンパイルしたら早かったけども.([1..30]ってすると,やっぱり遅い)


次は,条件式を使って.先ずはif文.

fib :: Integer -> Integer
fib n = if n == 1 || n == 2 then 1 else fib (n - 1) + fib (n - 2)

短い.そして,言うほど宇宙語じみてない.


case文.

fib :: Integer -> Integer
fib n = case n of
	  	1 -> 1
		2 -> 1
		_ -> fib (n - 1) + fib (n - 2)

_が気になる.


ガード?パターン照合の一種だとか.if文やcase文を読みにくくかっこよくしただけじゃないのかコレは.

fib :: Integer -> Integer
fib n |       (n == 1 || n == 2) = 1
        | not (n == 1 && n == 2) = fib (n - 1) + fib (n -2)

数学チックだなぁ.

追記

前にやった,lambdaってなんだ? - もちフィボナッチ数列計算のと早さを比べると,圧倒的にRubyのほうが早かった.そりゃ,ただ足し合わせてるだけだものね.

追記+1

相当気持ち悪いけど,高速化.

main = print $ map (fib 0 1) [1 .. 20]

fib :: Integer -> Integer -> Integer -> Integer
fib n m f = if f > 2 then fib m (n + m) (f - 1) else n + m

実行結果は同じです.段違いに早くなった.なんせただ足し合わせてるだけですもの.しかし気持ち悪い.