module Effectful.Writer.Static.Local
(
Writer
, runWriter
, execWriter
, tell
, listen
, listens
) where
import Control.Exception (onException, mask)
import Effectful
import Effectful.Dispatch.Static
import Effectful.Dispatch.Static.Primitive
data Writer w :: Effect
type instance DispatchOf (Writer w) = Static NoSideEffects
newtype instance StaticRep (Writer w) = Writer w
runWriter :: Monoid w => Eff (Writer w : es) a -> Eff es (a, w)
runWriter :: forall w (es :: [(Type -> Type) -> Type -> Type]) a.
Monoid w =>
Eff (Writer w : es) a -> Eff es (a, w)
runWriter Eff (Writer w : es) a
m = do
(a
a, Writer w
w) <- forall (e :: (Type -> Type) -> Type -> Type)
(sideEffects :: SideEffects)
(es :: [(Type -> Type) -> Type -> Type]) a.
(DispatchOf e ~ 'Static sideEffects, MaybeIOE sideEffects es) =>
StaticRep e -> Eff (e : es) a -> Eff es (a, StaticRep e)
runStaticRep (forall w. w -> StaticRep (Writer w)
Writer forall a. Monoid a => a
mempty) Eff (Writer w : es) a
m
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (a
a, w
w)
execWriter :: Monoid w => Eff (Writer w : es) a -> Eff es w
execWriter :: forall w (es :: [(Type -> Type) -> Type -> Type]) a.
Monoid w =>
Eff (Writer w : es) a -> Eff es w
execWriter Eff (Writer w : es) a
m = do
Writer w
w <- forall (e :: (Type -> Type) -> Type -> Type)
(sideEffects :: SideEffects)
(es :: [(Type -> Type) -> Type -> Type]) a.
(DispatchOf e ~ 'Static sideEffects, MaybeIOE sideEffects es) =>
StaticRep e -> Eff (e : es) a -> Eff es (StaticRep e)
execStaticRep (forall w. w -> StaticRep (Writer w)
Writer forall a. Monoid a => a
mempty) Eff (Writer w : es) a
m
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure w
w
tell :: (Writer w :> es, Monoid w) => w -> Eff es ()
tell :: forall w (es :: [(Type -> Type) -> Type -> Type]).
(Writer w :> es, Monoid w) =>
w -> Eff es ()
tell w
w = forall (e :: (Type -> Type) -> Type -> Type)
(sideEffects :: SideEffects)
(es :: [(Type -> Type) -> Type -> Type]) a.
(DispatchOf e ~ 'Static sideEffects, e :> es) =>
(StaticRep e -> (a, StaticRep e)) -> Eff es a
stateStaticRep forall a b. (a -> b) -> a -> b
$ \(Writer w
w0) -> ((), forall w. w -> StaticRep (Writer w)
Writer (w
w0 forall a. Semigroup a => a -> a -> a
<> w
w))
listen :: (Writer w :> es, Monoid w) => Eff es a -> Eff es (a, w)
listen :: forall w (es :: [(Type -> Type) -> Type -> Type]) a.
(Writer w :> es, Monoid w) =>
Eff es a -> Eff es (a, w)
listen Eff es a
m = forall (es :: [(Type -> Type) -> Type -> Type]) a.
(Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> forall b. ((forall a. IO a -> IO a) -> IO b) -> IO b
mask forall a b. (a -> b) -> a -> b
$ \forall a. IO a -> IO a
unmask -> do
w
w0 <- forall (e :: (Type -> Type) -> Type -> Type)
(es :: [(Type -> Type) -> Type -> Type]) a.
(e :> es) =>
Env es
-> (EffectRep (DispatchOf e) e
-> IO (a, EffectRep (DispatchOf e) e))
-> IO a
stateEnv Env es
es forall a b. (a -> b) -> a -> b
$ \(Writer w
w) -> forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (w
w, forall w. w -> StaticRep (Writer w)
Writer forall a. Monoid a => a
mempty)
a
a <- forall a. IO a -> IO a
unmask (forall (es :: [(Type -> Type) -> Type -> Type]) a.
Eff es a -> Env es -> IO a
unEff Eff es a
m Env es
es) forall a b. IO a -> IO b -> IO a
`onException` forall {a} {es :: [(Type -> Type) -> Type -> Type]}.
(Writer a :> es, Semigroup a) =>
Env es -> a -> IO a
merge Env es
es w
w0
(a
a, ) forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> forall {a} {es :: [(Type -> Type) -> Type -> Type]}.
(Writer a :> es, Semigroup a) =>
Env es -> a -> IO a
merge Env es
es w
w0
where
merge :: Env es -> a -> IO a
merge Env es
es a
w0 =
forall (e :: (Type -> Type) -> Type -> Type)
(es :: [(Type -> Type) -> Type -> Type]) a.
(e :> es) =>
Env es
-> (EffectRep (DispatchOf e) e
-> IO (a, EffectRep (DispatchOf e) e))
-> IO a
stateEnv Env es
es forall a b. (a -> b) -> a -> b
$ \(Writer a
w1) -> forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (a
w1, forall w. w -> StaticRep (Writer w)
Writer (a
w0 forall a. Semigroup a => a -> a -> a
<> a
w1))
listens :: (Writer w :> es, Monoid w) => (w -> b) -> Eff es a -> Eff es (a, b)
listens :: forall w (es :: [(Type -> Type) -> Type -> Type]) b a.
(Writer w :> es, Monoid w) =>
(w -> b) -> Eff es a -> Eff es (a, b)
listens w -> b
f Eff es a
m = do
(a
a, w
w) <- forall w (es :: [(Type -> Type) -> Type -> Type]) a.
(Writer w :> es, Monoid w) =>
Eff es a -> Eff es (a, w)
listen Eff es a
m
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (a
a, w -> b
f w
w)