{-# LANGUAGE NoImplicitPrelude,
MultiParamTypeClasses, FunctionalDependencies,
FlexibleInstances, FlexibleContexts, TypeSynonymInstances,
UndecidableInstances, TypeFamilies #-}
module Control.Monad.Memo.Array
(
Array,
ArrayCache,
ArrayMemo,
evalArrayMemo,
runArrayMemo,
UArray,
UArrayCache,
UArrayMemo,
evalUArrayMemo,
runUArrayMemo,
Container(..),
Cache,
genericEvalArrayMemo,
genericRunArrayMemo
) where
import Data.Function
import Data.Maybe (Maybe(..))
import Data.Array.ST
import Data.Array.IO
import Control.Monad
import Control.Monad.Trans.Class
import Control.Monad.ST
import System.IO
import Data.MaybeLike
import Control.Monad.Memo.Class
import Control.Monad.Trans.Memo.ReaderCache
newtype Container arr = Container { forall arr. Container arr -> arr
toArray :: arr }
type Cache arr k e = ReaderCache (Container (arr k e))
instance (Monad m, Ix k, MaybeLike e v, MArray c e m) =>
MonadCache k v (Cache c k e m) where
{-# INLINE lookup #-}
lookup :: k -> Cache c k e m (Maybe v)
lookup k
k = do
c <- ReaderCache (Container (c k e)) m (Container (c k e))
forall (m :: * -> *) c. Monad m => ReaderCache c m c
container
e <- lift $ readArray (toArray c) k
return (if isNothing e then Nothing else Just (fromJust e))
{-# INLINE add #-}
add :: k -> v -> Cache c k e m ()
add k
k v
v = do
c <- ReaderCache (Container (c k e)) m (Container (c k e))
forall (m :: * -> *) c. Monad m => ReaderCache c m c
container
lift $ writeArray (toArray c) k (just v)
instance (Monad m, Ix k, MaybeLike e v, MArray c e m) =>
MonadMemo k v (Cache c k e m) where
{-# INLINE memo #-}
memo :: (k -> Cache c k e m v) -> k -> Cache c k e m v
memo k -> Cache c k e m v
f k
k = do
c <- ReaderCache (Container (c k e)) m (Container (c k e))
forall (m :: * -> *) c. Monad m => ReaderCache c m c
container
e <- lift $ readArray (toArray c) k
if isNothing e
then do
v <- f k
lift $ writeArray (toArray c) k (just v)
return v
else return (fromJust e)
type family Array (m :: * -> *) :: * -> * -> *
type instance Array (ST s) = STArray s
type instance Array IO = IOArray
type instance Array (ReaderCache c (ST s)) = STArray s
type instance Array (ReaderCache c IO) = IOArray
type ArrayCache k e m = Cache (Array m) k e m
class MaybeLike e v => ArrayMemo v e | v -> e
evalArrayMemo :: (Ix k, MArray (Array m) e m, ArrayMemo v e) =>
ArrayCache k e m a
-> (k,k)
-> m a
{-# INLINE evalArrayMemo #-}
evalArrayMemo :: forall k (m :: * -> *) e v a.
(Ix k, MArray (Array m) e m, ArrayMemo v e) =>
ArrayCache k e m a -> (k, k) -> m a
evalArrayMemo = Cache (Array m) k e m a -> (k, k) -> m a
forall k e v (arr :: * -> * -> *) (m :: * -> *) a.
(Ix k, MaybeLike e v, MArray arr e m) =>
Cache arr k e m a -> (k, k) -> m a
genericEvalArrayMemo
runArrayMemo :: (Ix k, MArray (Array m) e m, ArrayMemo v e) =>
ArrayCache k e m a
-> (k,k)
-> m (a, Array m k e)
{-# INLINE runArrayMemo #-}
runArrayMemo :: forall k (m :: * -> *) e v a.
(Ix k, MArray (Array m) e m, ArrayMemo v e) =>
ArrayCache k e m a -> (k, k) -> m (a, Array m k e)
runArrayMemo = Cache (Array m) k e m a -> (k, k) -> m (a, Array m k e)
forall k e v (arr :: * -> * -> *) (m :: * -> *) a.
(Ix k, MaybeLike e v, MArray arr e m) =>
Cache arr k e m a -> (k, k) -> m (a, arr k e)
genericRunArrayMemo
type family UArray (m :: * -> *) :: * -> * -> *
type instance UArray (ST s) = STUArray s
type instance UArray IO = IOUArray
type instance UArray (ReaderCache c (ST s)) = STUArray s
type instance UArray (ReaderCache c IO) = IOUArray
type UArrayCache k e m = Cache (UArray m) k e m
class MaybeLike e v => UArrayMemo v e | v -> e
evalUArrayMemo :: (Ix k, MArray (UArray m) e m, UArrayMemo v e) =>
UArrayCache k e m a
-> (k,k)
-> m a
{-# INLINE evalUArrayMemo #-}
evalUArrayMemo :: forall k (m :: * -> *) e v a.
(Ix k, MArray (UArray m) e m, UArrayMemo v e) =>
UArrayCache k e m a -> (k, k) -> m a
evalUArrayMemo = Cache (UArray m) k e m a -> (k, k) -> m a
forall k e v (arr :: * -> * -> *) (m :: * -> *) a.
(Ix k, MaybeLike e v, MArray arr e m) =>
Cache arr k e m a -> (k, k) -> m a
genericEvalArrayMemo
runUArrayMemo :: (Ix k, MArray (UArray m) e m, UArrayMemo v e) =>
UArrayCache k e m a
-> (k,k)
-> m (a, UArray m k e)
{-# INLINE runUArrayMemo #-}
runUArrayMemo :: forall k (m :: * -> *) e v a.
(Ix k, MArray (UArray m) e m, UArrayMemo v e) =>
UArrayCache k e m a -> (k, k) -> m (a, UArray m k e)
runUArrayMemo = Cache (UArray m) k e m a -> (k, k) -> m (a, UArray m k e)
forall k e v (arr :: * -> * -> *) (m :: * -> *) a.
(Ix k, MaybeLike e v, MArray arr e m) =>
Cache arr k e m a -> (k, k) -> m (a, arr k e)
genericRunArrayMemo
genericEvalArrayMemo :: (Ix k, MaybeLike e v, MArray arr e m) =>
Cache arr k e m a -> (k, k) -> m a
{-# INLINE genericEvalArrayMemo #-}
genericEvalArrayMemo :: forall k e v (arr :: * -> * -> *) (m :: * -> *) a.
(Ix k, MaybeLike e v, MArray arr e m) =>
Cache arr k e m a -> (k, k) -> m a
genericEvalArrayMemo Cache arr k e m a
m (k, k)
lu = do
arr <- (k, k) -> e -> m (arr k e)
forall i. Ix i => (i, i) -> e -> m (arr i e)
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
(i, i) -> e -> m (a i e)
newArray (k, k)
lu e
forall a v. MaybeLike a v => a
nothing
evalReaderCache m (Container arr)
genericRunArrayMemo :: (Ix k, MaybeLike e v, MArray arr e m) =>
Cache arr k e m a -> (k, k) -> m (a, arr k e)
{-# INLINE genericRunArrayMemo #-}
genericRunArrayMemo :: forall k e v (arr :: * -> * -> *) (m :: * -> *) a.
(Ix k, MaybeLike e v, MArray arr e m) =>
Cache arr k e m a -> (k, k) -> m (a, arr k e)
genericRunArrayMemo Cache arr k e m a
m (k, k)
lu = do
arr <- (k, k) -> e -> m (arr k e)
forall i. Ix i => (i, i) -> e -> m (arr i e)
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
(i, i) -> e -> m (a i e)
newArray (k, k)
lu e
forall a v. MaybeLike a v => a
nothing
a <- evalReaderCache m (Container arr)
return (a, arr)