{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleContexts #-}
-- | Create unique Enumerable values.
module Control.Eff.Fresh( Fresh
, fresh
, runFresh
) where
import Data.Typeable
import Control.Eff
-- | Create unique Enumerable values.
newtype Fresh i v = Fresh (i -> v)
deriving (Functor, Typeable)
-- | Produce a value that has not been previously produced.
fresh :: (Typeable i, Enum i, Member (Fresh i) r) => Eff r i
fresh = send (inj . Fresh)
-- | Run an effect requiring unique values.
runFresh :: (Typeable i, Enum i) => Eff (Fresh i :> r) w -> i -> Eff r w
runFresh m s0 = loop s0 (admin m)
where
loop _ (Val x) = return x
loop s (E u) = handleRelay u (loop s) $
\(Fresh k) -> (loop $! succ s) (k s)