{- | Module : Control.Monad.Trans.Memo.StateCache Copyright : (c) Eduard Sergeev 2013 License : BSD-style (see the file LICENSE) Maintainer : eduard.sergeev@gmail.com Stability : experimental Portability : non-portable (multi-param classes, flexible instances) Generic StateCache - wrapper around `Control.Monad.Trans.State.Strict.StateT` -} {-# LANGUAGE GeneralizedNewtypeDeriving, TypeFamilies, MultiParamTypeClasses, FlexibleInstances, FlexibleContexts #-} module Control.Monad.Trans.Memo.StateCache ( StateCache, runStateCache, container, setContainer, evalStateCache ) where import Control.Monad.Primitive import Control.Monad.ST import Data.Array.MArray import Data.Function import Control.Applicative import Control.Monad import Control.Monad.IO.Class import Control.Monad.Fix import Control.Monad.Trans.Class import Control.Monad.Trans.State.Strict import Data.Array.Base import Data.Array.IO import Data.Array.ST newtype StateCache c m a = StateCache { toStateT :: StateT c m a } deriving (Functor, Applicative, Alternative, Monad, MonadPlus, MonadFix, MonadTrans, MonadIO) {-# INLINE runStateCache #-} runStateCache :: StateCache s m a -> s -> m (a, s) runStateCache = runStateT . toStateT -- | Evaluates computation discarding the resulting container evalStateCache :: Monad m => StateCache c m a -> c -> m a {-# INLINE evalStateCache #-} evalStateCache = evalStateT . toStateT -- | Returns internal container container :: Monad m => StateCache c m c {-# INLINE container #-} container = StateCache get -- | Assigns new value to internal container setContainer :: Monad m => c -> StateCache c m () {-# INLINE setContainer #-} setContainer = StateCache . put instance PrimMonad m => PrimMonad (StateCache c m) where type PrimState (StateCache c m) = PrimState m primitive = lift . primitive instance MArray IOArray e (StateCache c IO) where getBounds = lift . getBounds getNumElements = lift . getNumElements newArray a = lift . newArray a unsafeRead a = lift . unsafeRead a unsafeWrite a i = lift . unsafeWrite a i instance MArray IOUArray e IO => MArray IOUArray e (StateCache c IO) where getBounds = lift . getBounds getNumElements = lift . getNumElements newArray a = lift . newArray a unsafeRead a = lift . unsafeRead a unsafeWrite a i = lift . unsafeWrite a i instance MArray (STArray s) e (StateCache c (ST s)) where getBounds = lift . getBounds getNumElements = lift . getNumElements newArray a = lift . newArray a unsafeRead a = lift . unsafeRead a unsafeWrite a i = lift . unsafeWrite a i instance MArray (STUArray s) e (ST s) => MArray (STUArray s) e (StateCache c (ST s)) where getBounds = lift . getBounds getNumElements = lift . getNumElements newArray a = lift . newArray a unsafeRead a = lift . unsafeRead a unsafeWrite a i = lift . unsafeWrite a i