    {- |
    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 :: forall (m :: * -> *) k v a.
    Monad m =>
    MemoT k v m a -> Map k v -> m (a, Map k v)
    runMemoT = MemoStateT (Map k v) (ZonkAny 7) (ZonkAny 6) 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 :: forall (m :: * -> *) k v a.
    Monad m =>
    MemoT k v m a -> Map k v -> m a
    evalMemoT = MemoStateT (Map k v) (ZonkAny 5) (ZonkAny 4) 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 :: forall (m :: * -> *) k v a.
    Monad m =>
    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 :: forall (m :: * -> *) k v a. Monad m => 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 :: forall k v a. Memo k v a -> Map k v -> (a, Map k v)
    runMemo = MemoState (Map k v) (ZonkAny 3) (ZonkAny 2) 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 :: forall k v a. Memo k v a -> Map k v -> a
    evalMemo = MemoState (Map k v) (ZonkAny 1) (ZonkAny 0) 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 :: forall k v a. 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 :: forall k v a. 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)