{- |
Module      :  Control.Monad.Trans.Memo.Map
Copyright   :  (c) Eduard Sergeev 2011
License     :  BSD-style (see the file LICENSE)

Maintainer  :  eduard.sergeev@gmail.com
Stability   :  experimental
Portability :  non-portable (multi-param classes, functional dependencies)

Specialization of `MemoStateT` with `Data.Map` as a container

-}

{-# LANGUAGE NoImplicitPrelude #-}

module Control.Monad.Trans.Memo.Map
(

   -- * MemoT monad transformer
   MemoT,
   runMemoT,
   evalMemoT,
   startRunMemoT,
   startEvalMemoT,
   -- * Memo monad
   Memo,
   runMemo,
   evalMemo,
   startRunMemo,
   startEvalMemo,

) where

import Data.Functor.Identity
import Control.Monad
import Control.Monad.Trans.Memo.State

import Data.MapLike.Instances()
import qualified Data.Map as M


-- | Memoization monad transformer which uses `Data.Map` as a cache container
type MemoT k v = MemoStateT (M.Map k v) k v

-- | Given an initial cache, compute the result of a memoized computation
-- along with the final state of the cache
runMemoT :: Monad m => MemoT k v m a -> M.Map k v -> m (a, M.Map k v)
runMemoT :: MemoT k v m a -> Map k v -> m (a, Map k v)
runMemoT = MemoT k v m a -> Map k v -> m (a, Map k v)
forall (m :: * -> *) s k v a.
Monad m =>
MemoStateT s k v m a -> s -> m (a, s)
runMemoStateT

-- | Given an initial state, compute the result of a memoized computation
-- discarding the final state of the cache
evalMemoT :: Monad m => MemoT k v m a -> M.Map k v -> m a
evalMemoT :: MemoT k v m a -> Map k v -> m a
evalMemoT = MemoT k v m a -> Map k v -> m a
forall (m :: * -> *) c k v a.
Monad m =>
MemoStateT c k v m a -> c -> m a
evalMemoStateT

-- | Compute the result of memoized computation along with the final state of the cache.
-- This function uses empty `M.Map` as an initial state
startRunMemoT :: Monad m => MemoT k v m a -> m (a, M.Map k v)
startRunMemoT :: MemoT k v m a -> m (a, Map k v)
startRunMemoT = (MemoT k v m a -> Map k v -> m (a, Map k v)
forall (m :: * -> *) k v a.
Monad m =>
MemoT k v m a -> Map k v -> m (a, Map k v)
`runMemoT` Map k v
forall k a. Map k a
M.empty)

-- | Compute the result of a memoized computation discarding the final state of the cache.
-- This function uses empty `M.Map` as an initial state
startEvalMemoT :: Monad m => MemoT k v m a -> m a
startEvalMemoT :: MemoT k v m a -> m a
startEvalMemoT = (MemoT k v m a -> Map k v -> m a
forall (m :: * -> *) k v a.
Monad m =>
MemoT k v m a -> Map k v -> m a
`evalMemoT` Map k v
forall k a. Map k a
M.empty)


-- | Memoization monad which uses `Data.Map` as a cache container
type Memo k v = MemoT k v Identity

-- | Given an initial cache, compute the result of a memoized computation
-- along with the final state of the cache
runMemo :: Memo k v a -> M.Map k v -> (a, M.Map k v)
runMemo :: Memo k v a -> Map k v -> (a, Map k v)
runMemo = Memo k v a -> Map k v -> (a, Map k v)
forall c k v a. MemoState c k v a -> c -> (a, c)
runMemoState

-- | Given an initial state, compute the result of a memoized computation
-- discarding the final state of the cache
evalMemo :: Memo k v a -> M.Map k v -> a
evalMemo :: Memo k v a -> Map k v -> a
evalMemo = Memo k v a -> Map k v -> a
forall c k v a. MemoState c k v a -> c -> a
evalMemoState

-- | Compute the result of memoized computation along with the final state of the cache.
-- This function uses empty `M.Map` as an initial state
startRunMemo :: Memo k v a -> (a, M.Map k v)
startRunMemo :: Memo k v a -> (a, Map k v)
startRunMemo = (Memo k v a -> Map k v -> (a, Map k v)
forall k v a. Memo k v a -> Map k v -> (a, Map k v)
`runMemo` Map k v
forall k a. Map k a
M.empty)

-- | Compute the result of a memoized computation discarding the final state of the cache.
-- This function uses empty `M.Map` as an initial state
startEvalMemo :: Memo k v a -> a
startEvalMemo :: Memo k v a -> a
startEvalMemo = (Memo k v a -> Map k v -> a
forall k v a. Memo k v a -> Map k v -> a
`evalMemo` Map k v
forall k a. Map k a
M.empty)