{-# LANGUAGE FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses, TypeOperators, UndecidableInstances #-}
module Control.Carrier.Fresh.Strict
(
runFresh
, evalFresh
, FreshC(..)
, module Control.Effect.Fresh
) where
import Control.Algebra
import Control.Applicative (Alternative(..))
import Control.Carrier.State.Strict
import Control.Effect.Fresh
import Control.Monad (MonadPlus(..))
import qualified Control.Monad.Fail as Fail
import Control.Monad.Fix
import Control.Monad.IO.Class
import Control.Monad.Trans.Class
runFresh :: Int -> FreshC m a -> m (Int, a)
runFresh n (FreshC m) = runState n m
evalFresh :: Functor m => Int -> FreshC m a -> m a
evalFresh n (FreshC m) = evalState n m
newtype FreshC m a = FreshC (StateC Int m a)
deriving (Alternative, Applicative, Functor, Monad, Fail.MonadFail, MonadFix, MonadIO, MonadPlus, MonadTrans)
instance (Algebra sig m, Effect sig) => Algebra (Fresh :+: sig) (FreshC m) where
alg (L (Fresh k)) = FreshC (get <* modify (+ (1 :: Int))) >>= k
alg (R other) = FreshC (alg (R (handleCoercible other)))
{-# INLINE alg #-}