Следует отметить, что для такой задачи «каноническим» (и более быстрым) способом является определение чисел как бесконечного потока, например:
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
takeWhile (<100) fibs
--[0,1,1,2,3,5,8,13,21,34,55,89]
Рекурсивное определение может выглядеть страшно (или даже«Волшебный»), но если вы «думаете ленивый», это будет иметь смысл.
«Нечеткий» (и в некотором смысле более «императивный») способ определить такой бесконечный список:
fibs = map fst $ iterate (\(a,b) -> (b,a+b)) (0,1)
[Редактировать]
Для эффективного прямого вычисления (без бесконечного списка) вы можете использовать умножение матриц :
fib n = second $ (0,1,1,1) ** n where
p ** 0 = (1,0,0,1)
p ** 1 = p
p ** n | even n = (p `x` p) ** (n `div` 2)
| otherwise = p `x` (p ** (n-1))
(a,b,c,d) `x` (q,r,s,t) = (a*q+b*s, a*r+b*t,c*q+d*s,c*r+d*t)
second (_,f,_,_) = f
(Это было действительно весело писать, но я всегда благодарен за предложения)