{-# LANGUAGE DeriveFunctor, ExistentialQuantification, FlexibleContexts, FlexibleInstances, LambdaCase, MultiParamTypeClasses, StandaloneDeriving, TypeOperators, UndecidableInstances #-}
module Control.Effect.Fresh
( Fresh(..)
, fresh
, resetFresh
, runFresh
, FreshC(..)
) where
import Control.Effect.Carrier
import Control.Effect.Internal
import Control.Effect.Sum
data Fresh m k
= Fresh (Int -> k)
| forall b . Reset (m b) (b -> k)
deriving instance Functor (Fresh m)
instance HFunctor Fresh where
hmap _ (Fresh k) = Fresh k
hmap f (Reset m k) = Reset (f m) k
instance Effect Fresh where
handle state handler (Fresh k) = Fresh (handler . (<$ state) . k)
handle state handler (Reset m k) = Reset (handler (m <$ state)) (handler . fmap k)
fresh :: (Member Fresh sig, Carrier sig m) => m Int
fresh = send (Fresh ret)
resetFresh :: (Member Fresh sig, Carrier sig m) => m a -> m a
resetFresh m = send (Reset m ret)
runFresh :: (Carrier sig m, Effect sig, Monad m) => Eff (FreshC m) a -> m a
runFresh = fmap snd . flip runFreshC 0 . interpret
newtype FreshC m a = FreshC { runFreshC :: Int -> m (Int, a) }
instance (Carrier sig m, Effect sig, Monad m) => Carrier (Fresh :+: sig) (FreshC m) where
ret a = FreshC (\ i -> ret (i, a))
eff op = FreshC (\ i -> handleSum (eff . handleState i runFreshC) (\case
Fresh k -> runFreshC (k i) (succ i)
Reset m k -> runFreshC m i >>= flip runFreshC i . k . snd) op)