{-# LANGUAGE BangPatterns #-} import Control.Monad.ST import qualified Data.Vector.Fusion.Stream.Monadic as VFSM import qualified Data.Vector.Unboxed as VU import qualified Data.Vector.Unboxed.Mutable as VUM main :: IO () main = readLn >>= print . fib fib :: Int -> Int fib n = runST $ do ret <- VUM.unsafeNew (n + 1) VUM.unsafeWrite ret 0 (1 :: Int) VUM.unsafeWrite ret 1 (1 :: Int) rep n $ \i -> do a <- VUM.unsafeRead ret (i - 2) b <- VUM.unsafeRead ret (i - 1) VUM.unsafeWrite ret i (a + b) return =<< VU.last <$> VU.unsafeFreeze ret stream :: Monad m => Int -> Int -> VFSM.Stream m Int stream !l !r = VFSM.Stream step l where step x | x < r = return $ VFSM.Yield x (x + 1) | otherwise = return $ VFSM.Done {-# INLINE [0] step #-} {-# INLINE [1] stream #-} rep :: Monad m => Int -> (Int -> m ()) -> m () rep n = flip VFSM.mapM_ (stream 2 (n + 1)) {-# INLINE rep #-}