{-# LANGUAGE NoImplicitPrelude,
MultiParamTypeClasses, FunctionalDependencies,
FlexibleInstances, FlexibleContexts, TypeFamilies,
UndecidableInstances, TypeSynonymInstances #-}
module Control.Monad.Memo.Vector
(
Vector,
VectorCache,
VectorMemo,
evalVectorMemo,
runVectorMemo,
UVector,
UVectorCache,
UVectorMemo,
evalUVectorMemo,
runUVectorMemo,
Container(..),
Cache,
genericEvalVectorMemo,
genericRunVectorMemo
) where
import Data.Int
import Data.Function
import Data.Maybe (Maybe(..))
import Data.Vector.Generic.Mutable
import qualified Data.Vector.Mutable as M
import qualified Data.Vector.Unboxed.Mutable as UM
import Control.Applicative
import Control.Monad
import Control.Monad.Fix
import Control.Monad.Trans.Class
import Control.Monad.Primitive
import Data.MaybeLike
import Control.Monad.Memo.Class
import Control.Monad.Trans.Memo.ReaderCache
newtype Container vec = Container { toVector :: vec }
type Cache vec s e = ReaderCache (Container (vec s e))
instance (PrimMonad m, PrimState m ~ s, MaybeLike e v, MVector c e) =>
MonadCache Int v (Cache c s e m) where
{-# INLINE lookup #-}
lookup k = do
c <- container
e <- lift $ read (toVector c) k
return (if isNothing e then Nothing else Just (fromJust e))
{-# INLINE add #-}
add k v = do
c <- container
lift $ write (toVector c) k (just v)
instance (PrimMonad m, PrimState m ~ s, MaybeLike e v, MVector c e) =>
MonadMemo Int v (Cache c s e m) where
{-# INLINE memo #-}
memo f k = do
c <- container
e <- lift $ read (toVector c) k
if isNothing e
then do
v <- f k
lift $ write (toVector c) k (just v)
return v
else return (fromJust e)
type Vector = M.MVector
type VectorCache s e = Cache Vector s e
class MaybeLike e v => VectorMemo v e | v -> e
evalVectorMemo :: (PrimMonad m, VectorMemo v e) =>
VectorCache (PrimState m) e m a
-> Int
-> m a
{-# INLINE evalVectorMemo #-}
evalVectorMemo = genericEvalVectorMemo
runVectorMemo :: (PrimMonad m, VectorMemo v e) =>
VectorCache (PrimState m) e m a
-> Int
-> m (a, Vector (PrimState m) e)
{-# INLINE runVectorMemo #-}
runVectorMemo = genericRunVectorMemo
type UVector = UM.MVector
type UVectorCache s e = Cache UVector s e
class MaybeLike e v => UVectorMemo v e | v -> e
evalUVectorMemo :: (PrimMonad m, MVector UVector e, UVectorMemo v e) =>
UVectorCache (PrimState m) e m a
-> Int
-> m a
{-# INLINE evalUVectorMemo #-}
evalUVectorMemo = genericEvalVectorMemo
runUVectorMemo :: (PrimMonad m, MVector UVector e, UVectorMemo v e) =>
UVectorCache (PrimState m) e m a
-> Int
-> m (a, UVector (PrimState m) e)
{-# INLINE runUVectorMemo #-}
runUVectorMemo = genericRunVectorMemo
genericEvalVectorMemo :: (MaybeLike e v, PrimMonad m, MVector c e) =>
Cache c (PrimState m) e m a -> Int -> m a
{-# INLINE genericEvalVectorMemo #-}
genericEvalVectorMemo m n = do
c <- replicate n nothing
evalReaderCache m (Container c)
genericRunVectorMemo :: (MaybeLike e v, PrimMonad m, MVector c e) =>
Cache c (PrimState m) e m a -> Int -> m (a, c (PrimState m) e)
{-# INLINE genericRunVectorMemo #-}
genericRunVectorMemo m n = do
c <- replicate n nothing
a <- evalReaderCache m (Container c)
return (a, c)