import Control.Monad.Reader (Reader, runReader, ask, local) main :: IO () main = do putStrLn ("Naive: " ++ show (fib_naive 10)) putStrLn ("Fast: " ++ show (fib_acc (0,1) 10)) putStrLn ("Reader: " ++ show (runReader (fib_reader 10) (0,1))) fib_naive :: Int -> Int fib_naive 0 = 0 fib_naive 1 = 1 fib_naive n = fib_naive (n - 1) + fib_naive (n - 2) fib_acc :: (Int, Int) -> Int -> Int fib_acc (i, j) 0 = i fib_acc (i, j) 1 = j fib_acc (i, j) n = fib_acc (j, i + j) (n - 1) fib_reader :: Int -> Reader (Int, Int) Int fib_reader n = do (i, j) <- ask case n of 0 -> return i 1 -> return j _ -> local (\(i, j) -> (j, i + j)) (fib_reader (n - 1))