-----------------------------------------------------------------------------

-- |

-- Module      :  Control.Effect.Writer.Lazy

-- Copyright   :  (c) Michael Szvetits, 2020

-- License     :  BSD3 (see the file LICENSE)

-- Maintainer  :  typedbyte@qualified.name

-- Stability   :  stable

-- Portability :  portable

--

-- Lazy interpretations of the 'Writer'' effect.

--

-- If you don't require disambiguation of multiple writer effects

-- (i.e., you only have one writer effect in your monadic context),

-- you usually need the untagged interpretations.

-----------------------------------------------------------------------------

module Control.Effect.Writer.Lazy
  ( -- * Tagged Interpretations

    execWriter'
  , runWriter'
    -- * Untagged Interpretations

  , execWriter
  , runWriter
  ) where

-- base

import Data.Tuple (swap)

-- transformers

import Control.Monad.Trans.Writer.Lazy (WriterT, execWriterT, runWriterT)

import Control.Effect.Writer    (Writer, Writer')
import Control.Effect.Machinery (G, Via, runVia)

-- | Runs the writer effect and returns the final output.

execWriter' :: forall tag w m a. Monad m
            => (Writer' tag w `Via` WriterT w) m a -- ^ The program whose writer effect should be handled.

            -> m w                                 -- ^ The program with its writer effect handled, producing the final output @w@.

execWriter' :: Via (Writer' tag w) (WriterT w) m a -> m w
execWriter' = WriterT w m a -> m w
forall (m :: * -> *) w a. Monad m => WriterT w m a -> m w
execWriterT (WriterT w m a -> m w)
-> (Via (Writer' tag w) (WriterT w) m a -> WriterT w m a)
-> Via (Writer' tag w) (WriterT w) m a
-> m w
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Via (Writer' tag w) (WriterT w) m a -> WriterT w m a
forall (effs :: [Effect]) (t :: Transformer) (m :: * -> *) a.
EachVia effs t m a -> t m a
runVia
{-# INLINE execWriter' #-}

-- | The untagged version of 'execWriter''.

execWriter :: Monad m => (Writer w `Via` WriterT w) m a -> m w
execWriter :: Via (Writer w) (WriterT w) m a -> m w
execWriter = forall k (tag :: k) w (m :: * -> *) a.
Monad m =>
Via (Writer' tag w) (WriterT w) m a -> m w
forall w (m :: * -> *) a.
Monad m =>
Via (Writer' G w) (WriterT w) m a -> m w
execWriter' @G
{-# INLINE execWriter #-}

-- | Runs the writer effect and returns both the final output and the result of the interpreted program.

runWriter' :: forall tag w m a. Functor m
           => (Writer' tag w `Via` WriterT w) m a -- ^ The program whose writer effect should be handled.

           -> m (w, a)                            -- ^ The program with its writer effect handled, producing the final output @w@ and the result @a@.

runWriter' :: Via (Writer' tag w) (WriterT w) m a -> m (w, a)
runWriter' = ((a, w) -> (w, a)) -> m (a, w) -> m (w, a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a, w) -> (w, a)
forall a b. (a, b) -> (b, a)
swap (m (a, w) -> m (w, a))
-> (Via (Writer' tag w) (WriterT w) m a -> m (a, w))
-> Via (Writer' tag w) (WriterT w) m a
-> m (w, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. WriterT w m a -> m (a, w)
forall w (m :: * -> *) a. WriterT w m a -> m (a, w)
runWriterT (WriterT w m a -> m (a, w))
-> (Via (Writer' tag w) (WriterT w) m a -> WriterT w m a)
-> Via (Writer' tag w) (WriterT w) m a
-> m (a, w)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Via (Writer' tag w) (WriterT w) m a -> WriterT w m a
forall (effs :: [Effect]) (t :: Transformer) (m :: * -> *) a.
EachVia effs t m a -> t m a
runVia
{-# INLINE runWriter' #-}

-- | The untagged version of 'runWriter''.

runWriter :: Functor m => (Writer w `Via` WriterT w) m a -> m (w, a)
runWriter :: Via (Writer w) (WriterT w) m a -> m (w, a)
runWriter = forall k (tag :: k) w (m :: * -> *) a.
Functor m =>
Via (Writer' tag w) (WriterT w) m a -> m (w, a)
forall w (m :: * -> *) a.
Functor m =>
Via (Writer' G w) (WriterT w) m a -> m (w, a)
runWriter' @G
{-# INLINE runWriter #-}