Your algorithm is not very good. You can improve it a bit using memoization, down to O (n). Using divide and conquer, you can go to O (log n):
import Data.Matrix fib :: Integer -> Integer fib n = ((fromLists [[1,1],[1,0]]) ^ n) ! (1,2)
The idea is that multiplication is associative, so you can put your curly braces in strategic places:
5 ^ 10 = (5 * 5 * 5 * 5 * 5) * (5 * 5 * 5 * 5 * 5) = (5 * 5 * 5 * 5 * 5) ^ 2 = ((5 * 5) * ( 5 * 5) * 5) ^ 2 = ((5 * 5) ^ 2 * 5) ^ 2 = (((5 ^ 2) ^ 2) * 5) ^ 2
The same pattern can be applied to matrix multiplication. And Haskell has already implemented this in its default library for (^) .
This really works:
map fib [1..21] --! [1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946]
source share