module Data.Function.YaMemo (
MemoTable(..)
, Memo
, memo
, memo' ) where
import "mtl" Control.Monad.State
import qualified Data.Map as M
class MemoTable t where
emptyMemoTable :: Ord a => t a b
lookupMemoTable :: Ord a => a -> t a b -> Maybe b
insertMemoTable :: Ord a => a -> b -> t a b -> t a b
class (Monad m) => MemoTableT t m where
emptyMemoTableT :: Ord a => t a (m b)
lookupMemoTableT :: Ord a => a -> t a (m b) -> Maybe (m b)
insertMemoTableT :: Ord a => a -> m b -> t a (m b) -> t a (m b)
instance MemoTable M.Map where
emptyMemoTable = M.empty
lookupMemoTable = M.lookup
insertMemoTable = M.insert
instance MemoTableT M.Map [] where
emptyMemoTableT = M.empty
lookupMemoTableT = M.lookup
insertMemoTableT = M.insert
type Memo t a b = a -> State (t a b) b
memoise :: (MemoTable t, Ord a) => Memo t a b -> Memo t a b
memoise mf x = do prev <- find x
case prev of
Just y -> return y
Nothing -> do y <- mf x
ins x y
return y
where find k = get >>= return . lookupMemoTable k
ins k v = get >>= put . insertMemoTable k v
evalMemo :: (MemoTable t, Ord a) => (Memo t) a b -> a -> b
evalMemo m v = evalState (m v) emptyMemoTable
runMemo :: (MemoTable t, Ord a) => t a b -> (Memo t) a b -> a -> (b, t a b)
runMemo tb m v = runState (m v) tb
gfun :: (b -> c) -> (c -> b) -> c
gfun = (fix .) . (.)
memoising :: (Ord a, MemoTable t)
=> ((a -> State (t a b) b) -> Memo t a b) -> a -> State (t a b) b
memoising = gfun memoise
memo :: (MemoTable t, Ord a)
=> (a -> State (t a b) b)
-> ((a -> State (t a b) b) -> Memo t a b)
-> (a -> b)
memo g f = evalMemo (asTypeOf (memoising f) g)
memo' :: (MemoTable t, Ord a)
=> ((a -> State (t a b) b) -> Memo t a b)
-> t a b
-> (a -> (t a b, b))
memo' = ((swap .) .) . flip runMemo . memoising
swap :: (a, b) -> (b, a)
swap (x,y) = (y,x)