{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}
module Data.Parameterized.Nonce.Transformers
( MonadNonce(..)
, NonceT(..)
, NonceST
, NonceIO
, getNonceSTGen
, runNonceST
, runNonceIO
, module Data.Parameterized.Nonce
) where
import Control.Monad.Reader
import Control.Monad.ST
import Control.Monad.State
import Data.Parameterized.Nonce
class Monad m => MonadNonce m where
type NonceSet m :: *
freshNonceM :: forall (tp :: k) . m (Nonce (NonceSet m) tp)
newtype NonceT s m a =
NonceT { runNonceT :: ReaderT (NonceGenerator m s) m a }
deriving (Functor, Applicative, Monad)
instance MonadTrans (NonceT s) where
lift m = NonceT $ lift m
instance Monad m => MonadNonce (NonceT s m) where
type NonceSet (NonceT s m) = s
freshNonceM = NonceT $ lift . freshNonce =<< ask
instance MonadNonce m => MonadNonce (StateT s m) where
type NonceSet (StateT s m) = NonceSet m
freshNonceM = lift $ freshNonceM
type NonceST t s = NonceT s (ST t)
type NonceIO s = NonceT s IO
getNonceSTGen :: NonceST t s (NonceGenerator (ST t) s)
getNonceSTGen = NonceT ask
runNonceST :: (forall t s. NonceST t s a) -> a
runNonceST m = runST $ withSTNonceGenerator $ runReaderT $ runNonceT m
runNonceIO :: (forall s. NonceIO s a) -> IO a
runNonceIO m = withIONonceGenerator $ runReaderT $ runNonceT m