{-# LANGUAGE NoImplicitPrelude, MultiParamTypeClasses,
FlexibleInstances, TypeSynonymInstances #-}
module Control.Monad.Trans.Memo.State
(
MemoStateT(..),
runMemoStateT,
evalMemoStateT,
MemoState,
runMemoState,
evalMemoState,
Container(..)
) where
import Data.Tuple
import Data.Function
import Data.Functor.Identity
import Control.Applicative
import Control.Monad
import Control.Monad.Trans.Class
import qualified Data.MapLike as M
import Control.Monad.Memo.Class
import Control.Monad.Trans.Memo.StateCache
newtype Container s = Container { toState :: s }
type MemoStateT s k v = StateCache (Container s)
runMemoStateT :: Monad m => MemoStateT s k v m a -> s -> m (a, s)
runMemoStateT m s = do
(a, c) <- runStateCache m (Container s)
return (a, toState c)
evalMemoStateT :: Monad m => MemoStateT c k v m a -> c -> m a
evalMemoStateT m s = runMemoStateT m s >>= return . fst
type MemoState c k v = MemoStateT c k v Identity
runMemoState :: MemoState c k v a -> c -> (a, c)
runMemoState m = runIdentity . runMemoStateT m
evalMemoState :: MemoState c k v a -> c -> a
evalMemoState m = runIdentity . evalMemoStateT m
instance (Monad m, M.MapLike c k v) => MonadCache k v (MemoStateT c k v m) where
{-# INLINE lookup #-}
lookup k = container >>= return . M.lookup k . toState
{-# INLINE add #-}
add k v = container >>= setContainer . Container . M.add k v . toState
instance (Monad m, M.MapLike c k v) => MonadMemo k v (MemoStateT c k v m) where
{-# INLINE memo #-}
memo = memol0