Last active
December 21, 2021 15:40
-
-
Save L-TChen/c9021b0b90dd9a85878b367f45970c8e to your computer and use it in GitHub Desktop.
Memoization with IntMap and State monad in Haskell
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE FlexibleContexts, BangPatterns #-} | |
import Data.IntMap.Strict | |
import Data.Maybe | |
import Data.Function | |
import Control.Monad.Identity | |
import Control.Monad.State.Lazy hiding (fix) | |
import Prelude hiding (lookup) | |
import Criterion.Main | |
fib :: (Monad m) => (Int -> m Integer) -> (Int -> m Integer) | |
fib _ 0 = return 0 | |
fib _ 1 = return 1 | |
fib f n = (+) <$> f (n-1) <*> f (n-2) | |
memoize :: (MonadState (IntMap v) m) => (Int -> m v) -> Int -> m v | |
memoize f x = do | |
v <- gets (lookup x) | |
case v of | |
Just y -> return y | |
_ -> do | |
y <- f x | |
modify $ insert x y | |
return y | |
naiveFib :: Int -> Integer | |
naiveFib n = runIdentity (fix fib n) | |
memoFib :: Int -> Integer | |
memoFib n = evalState (fix (memoize . fib) n) empty | |
fibs = 0 : 1 : zipWith (+) fibs (tail fibs) | |
tabFib = (fibs !!) | |
tailFib n = go 0 1 n | |
where | |
go !x0 !x1 0 = x0 | |
go !x0 !x1 !n = go x1 (x1+x0) (n-1) | |
main = defaultMain [ | |
bgroup "naiveFib" [ bench (show i) $ whnf naiveFib i | i <- range ], | |
bgroup "memoFib" [ bench (show i) $ whnf memoFib i | i <- range ], | |
bgroup "tailFib" [ bench (show i) $ whnf tailFib i | i <- range ], | |
bgroup "tabFib" [ bench (show i) $ whnf tabFib i | i <- range ] | |
] | |
where range = [9, 11..15] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment