-- | The 'Writer' as an effect.
module Effectful.Writer
  ( Writer
  , runWriter
  , execWriter
  , writer
  , tell
  , listen
  , listens
  ) where

import Data.Coerce
import qualified Data.Semigroup as S

import Effectful.Internal.Has
import Effectful.Internal.Monad

-- | Provide access to a write only value of type @w@.
newtype Writer w = Writer w
  deriving (b -> Writer w -> Writer w
NonEmpty (Writer w) -> Writer w
Writer w -> Writer w -> Writer w
(Writer w -> Writer w -> Writer w)
-> (NonEmpty (Writer w) -> Writer w)
-> (forall b. Integral b => b -> Writer w -> Writer w)
-> Semigroup (Writer w)
forall b. Integral b => b -> Writer w -> Writer w
forall w. Semigroup w => NonEmpty (Writer w) -> Writer w
forall w. Semigroup w => Writer w -> Writer w -> Writer w
forall w b. (Semigroup w, Integral b) => b -> Writer w -> Writer w
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: b -> Writer w -> Writer w
$cstimes :: forall w b. (Semigroup w, Integral b) => b -> Writer w -> Writer w
sconcat :: NonEmpty (Writer w) -> Writer w
$csconcat :: forall w. Semigroup w => NonEmpty (Writer w) -> Writer w
<> :: Writer w -> Writer w -> Writer w
$c<> :: forall w. Semigroup w => Writer w -> Writer w -> Writer w
S.Semigroup, Semigroup (Writer w)
Writer w
Semigroup (Writer w)
-> Writer w
-> (Writer w -> Writer w -> Writer w)
-> ([Writer w] -> Writer w)
-> Monoid (Writer w)
[Writer w] -> Writer w
Writer w -> Writer w -> Writer w
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
forall w. Monoid w => Semigroup (Writer w)
forall w. Monoid w => Writer w
forall w. Monoid w => [Writer w] -> Writer w
forall w. Monoid w => Writer w -> Writer w -> Writer w
mconcat :: [Writer w] -> Writer w
$cmconcat :: forall w. Monoid w => [Writer w] -> Writer w
mappend :: Writer w -> Writer w -> Writer w
$cmappend :: forall w. Monoid w => Writer w -> Writer w -> Writer w
mempty :: Writer w
$cmempty :: forall w. Monoid w => Writer w
$cp1Monoid :: forall w. Monoid w => Semigroup (Writer w)
Monoid)

runWriter :: Monoid w => Eff (Writer w : es) a -> Eff es (a, w)
runWriter :: Eff (Writer w : es) a -> Eff es (a, w)
runWriter = ((a, Writer w) -> (a, w)) -> Eff es (a, Writer w) -> Eff es (a, w)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a, Writer w) -> (a, w)
coerce (Eff es (a, Writer w) -> Eff es (a, w))
-> (Eff (Writer w : es) a -> Eff es (a, Writer w))
-> Eff (Writer w : es) a
-> Eff es (a, w)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Writer w -> Eff (Writer w : es) a -> Eff es (a, Writer w)
forall e (es :: [*]) a. e -> Eff (e : es) a -> Eff es (a, e)
runEffect Writer w
forall a. Monoid a => a
mempty

execWriter :: Monoid w => Eff (Writer w : es) a -> Eff es w
execWriter :: Eff (Writer w : es) a -> Eff es w
execWriter = (Writer w -> w) -> Eff es (Writer w) -> Eff es w
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Writer w -> w
coerce (Eff es (Writer w) -> Eff es w)
-> (Eff (Writer w : es) a -> Eff es (Writer w))
-> Eff (Writer w : es) a
-> Eff es w
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Writer w -> Eff (Writer w : es) a -> Eff es (Writer w)
forall e (es :: [*]) a. e -> Eff (e : es) a -> Eff es e
execEffect Writer w
forall a. Monoid a => a
mempty

writer :: (Writer w :> es, Monoid w) => (a, w) -> Eff es a
writer :: (a, w) -> Eff es a
writer (a
a, w
w) = (Writer w -> (a, Writer w)) -> Eff es a
forall e (es :: [*]) a. (e :> es) => (e -> (a, e)) -> Eff es a
stateEffect ((Writer w -> (a, Writer w)) -> Eff es a)
-> (Writer w -> (a, Writer w)) -> Eff es a
forall a b. (a -> b) -> a -> b
$ \Writer w
w0 -> (a
a, Writer w
w0 Writer w -> Writer w -> Writer w
forall a. Monoid a => a -> a -> a
`mappend` w -> Writer w
forall w. w -> Writer w
Writer w
w)

tell :: (Writer w :> es, Monoid w) => w -> Eff es ()
tell :: w -> Eff es ()
tell w
w = (Writer w -> ((), Writer w)) -> Eff es ()
forall e (es :: [*]) a. (e :> es) => (e -> (a, e)) -> Eff es a
stateEffect ((Writer w -> ((), Writer w)) -> Eff es ())
-> (Writer w -> ((), Writer w)) -> Eff es ()
forall a b. (a -> b) -> a -> b
$ \Writer w
w0 -> ((), Writer w
w0 Writer w -> Writer w -> Writer w
forall a. Monoid a => a -> a -> a
`mappend` w -> Writer w
forall w. w -> Writer w
Writer w
w)

listen
  :: (Writer w :> es, Monoid w)
  => Eff es a
  -> Eff es (a, w)
listen :: Eff es a -> Eff es (a, w)
listen = ((a, Writer w) -> (a, w)) -> Eff es (a, Writer w) -> Eff es (a, w)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(a
a, Writer w
w) -> (a
a, w
w)) (Eff es (a, Writer w) -> Eff es (a, w))
-> (Eff es a -> Eff es (a, Writer w)) -> Eff es a -> Eff es (a, w)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Eff es a -> Eff es (a, Writer w)
forall e (es :: [*]) a.
(e :> es, Monoid e) =>
Eff es a -> Eff es (a, e)
listenEffect

listens
  :: (Writer w :> es, Monoid w)
  => (w -> b)
  -> Eff es a
  -> Eff es (a, b)
listens :: (w -> b) -> Eff es a -> Eff es (a, b)
listens w -> b
f Eff es a
m = do
  (a
a, w
w) <- Eff es a -> Eff es (a, w)
forall w (es :: [*]) a.
(Writer w :> es, Monoid w) =>
Eff es a -> Eff es (a, w)
listen Eff es a
m
  (a, b) -> Eff es (a, b)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a
a, w -> b
f w
w)