in-other-words-0.1.0.0: src/Control/Effect/Regional.hs
{-# LANGUAGE DerivingVia #-}
module Control.Effect.Regional
( -- * Effects
Regional(..)
, Hoist
-- * Actions
, regionally
, hoist
-- * Interpretations
, runHoist
, hoistToFinal
-- * Threading utilities
, threadRegionalViaOptional
-- * Combinators for 'Algebra's
-- Intended to be used for custom 'Carrier' instances when
-- defining 'algPrims'.
, powerAlgHoist
, powerAlgHoistFinal
-- * Carriers
, HoistC
, HoistToFinalC
) where
import Control.Effect
import Control.Effect.Carrier
import Control.Effect.Type.Regional
import Control.Effect.Type.Optional
import Control.Effect.Internal.Regional
import Control.Monad.Trans.Control (control)
-- | Execute a computation modified in some way, providing
-- the interpreter of @'Regional' s@ a constant to indicate
-- how the computation should be modified.
regionally :: Eff (Regional s) m => s -> m a -> m a
regionally s m = send (Regionally s m)
{-# INLINE regionally #-}
-- | Lift a natural transformation of a base monad to the
-- current monad.
hoist :: Eff (Hoist b) m => (forall x. b x -> b x) -> m a -> m a
hoist n = regionally (HoistCall n)
{-# INLINE hoist #-}
type HoistToFinalC b = InterpretPrimC HoistToFinalH (Hoist b)
-- | Run a @'Hoist' m@ effect, where the base monad @m@ is the current monad.
--
-- @'Derivs' ('HoistC' m) = 'Hoist' m ': 'Derivs' m@
--
-- @'Prims' ('HoistC' m) = 'Hoist' m ': 'Prims' m@
runHoist :: Carrier m
=> HoistC m a
-> m a
runHoist = unHoistC
{-# INLINE runHoist #-}
-- | Run a @'Hoist' b@ effect, where the base monad @b@ is the final base monad.
--
-- @'Derivs' ('HoistToFinalC' b m) = 'Hoist' b ': 'Derivs' m@
--
-- @'Prims' ('HoistToFinalC' b m) = 'Hoist' b ': 'Prims' m@
hoistToFinal :: ( MonadBaseControl b m
, Carrier m
)
=> HoistToFinalC b m a
-> m a
hoistToFinal = interpretPrimViaHandler
{-# INLINE hoistToFinal #-}
-- | Strengthen an @'Algebra' p m@ by adding a @'Hoist' m@ handler
powerAlgHoist :: forall m p a
. Algebra' p m a
-> Algebra' (Hoist m ': p) m a
powerAlgHoist alg = powerAlg alg $ \(Regionally (HoistCall n) m) -> n m
{-# INLINE powerAlgHoist #-}
-- | Strengthen an @'Algebra' p m@ by adding a @'Hoist' b@ handler, where
-- @b@ is the final base monad.
powerAlgHoistFinal :: forall b m p a
. MonadBaseControl b m
=> Algebra' p m a
-> Algebra' (Hoist b ': p) m a
powerAlgHoistFinal alg = powerAlg alg $ \case
Regionally (HoistCall n) m -> control $ \lower -> n (lower m)
{-# INLINE powerAlgHoistFinal #-}