-- |
-- A class for monads supporting a supply of fresh names
--

module Control.Monad.Supply.Class where

import Prelude

import Control.Monad.RWS (MonadState(..), MonadTrans(..), RWST)
import Control.Monad.State (StateT)
import Control.Monad.Supply (SupplyT(..))
import Control.Monad.Writer (WriterT)
import Data.Text (Text, pack)

class Monad m => MonadSupply m where
  fresh :: m Integer
  peek :: m Integer
  default fresh :: (MonadTrans t, MonadSupply n, m ~ t n) => m Integer
  fresh = forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift forall (m :: * -> *). MonadSupply m => m Integer
fresh
  default peek :: (MonadTrans t, MonadSupply n, m ~ t n) => m Integer
  peek = forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift forall (m :: * -> *). MonadSupply m => m Integer
peek

instance Monad m => MonadSupply (SupplyT m) where
  fresh :: SupplyT m Integer
fresh = forall (m :: * -> *) a. StateT Integer m a -> SupplyT m a
SupplyT forall a b. (a -> b) -> a -> b
$ do
    Integer
n <- forall s (m :: * -> *). MonadState s m => m s
get
    forall s (m :: * -> *). MonadState s m => s -> m ()
put (Integer
n forall a. Num a => a -> a -> a
+ Integer
1)
    forall (m :: * -> *) a. Monad m => a -> m a
return Integer
n
  peek :: SupplyT m Integer
peek = forall (m :: * -> *) a. StateT Integer m a -> SupplyT m a
SupplyT forall s (m :: * -> *). MonadState s m => m s
get

instance MonadSupply m => MonadSupply (StateT s m)
instance (Monoid w, MonadSupply m) => MonadSupply (WriterT w m)
instance (Monoid w, MonadSupply m) => MonadSupply (RWST r w s m)

freshName :: MonadSupply m => m Text
freshName :: forall (m :: * -> *). MonadSupply m => m Text
freshName = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Text
"$" forall a. Semigroup a => a -> a -> a
<> ) forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> String
show) forall (m :: * -> *). MonadSupply m => m Integer
fresh