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

-- |

-- Module      :  Control.Effect.State.Lazy

-- Copyright   :  (c) Michael Szvetits, 2020

-- License     :  BSD3 (see the file LICENSE)

-- Maintainer  :  typedbyte@qualified.name

-- Stability   :  stable

-- Portability :  portable

--

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

--

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

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

-- you usually need the untagged interpretations.

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

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

    evalState'
  , execState'
  , runState'
    -- * Untagged Interpretations

  , evalState
  , execState
  , runState
  ) where

-- base

import Data.Tuple (swap)

-- transformers

import Control.Monad.Trans.State.Lazy (StateT, runStateT)

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

-- | Runs the state effect and discards the final state.

evalState' :: forall tag s m a. Functor m
           => s                                 -- ^ The initial state.

           -> (State' tag s `Via` StateT s) m a -- ^ The program whose state effect should be handled.

           -> m a                               -- ^ The program with its state effect handled.

evalState' :: s -> Via (State' tag s) (StateT s) m a -> m a
evalState' s :: s
s = ((a, s) -> a) -> m (a, s) -> m a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a, s) -> a
forall a b. (a, b) -> a
fst (m (a, s) -> m a)
-> (Via (State' tag s) (StateT s) m a -> m (a, s))
-> Via (State' tag s) (StateT s) m a
-> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (StateT s m a -> s -> m (a, s)) -> s -> StateT s m a -> m (a, s)
forall a b c. (a -> b -> c) -> b -> a -> c
flip StateT s m a -> s -> m (a, s)
forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
runStateT s
s (StateT s m a -> m (a, s))
-> (Via (State' tag s) (StateT s) m a -> StateT s m a)
-> Via (State' tag s) (StateT s) m a
-> m (a, s)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Via (State' tag s) (StateT s) m a -> StateT s m a
forall (effs :: [Effect]) (t :: Transformer) (m :: * -> *) a.
EachVia effs t m a -> t m a
runVia
{-# INLINE evalState' #-}

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

evalState :: Functor m => s -> (State s `Via` StateT s) m a -> m a
evalState :: s -> Via (State s) (StateT s) m a -> m a
evalState = forall k (tag :: k) s (m :: * -> *) a.
Functor m =>
s -> Via (State' tag s) (StateT s) m a -> m a
forall s (m :: * -> *) a.
Functor m =>
s -> Via (State' G s) (StateT s) m a -> m a
evalState' @G
{-# INLINE evalState #-}

-- | Runs the state effect and discards the result of the interpreted program.

execState' :: forall tag s m a. Functor m
           => s                                 -- ^ The initial state.

           -> (State' tag s `Via` StateT s) m a -- ^ The program whose state effect should be handled.

           -> m s                               -- ^ The program with its state effect handled, producing the final state @s@.

execState' :: s -> Via (State' tag s) (StateT s) m a -> m s
execState' s :: s
s = ((a, s) -> s) -> m (a, s) -> m s
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a, s) -> s
forall a b. (a, b) -> b
snd (m (a, s) -> m s)
-> (Via (State' tag s) (StateT s) m a -> m (a, s))
-> Via (State' tag s) (StateT s) m a
-> m s
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (StateT s m a -> s -> m (a, s)) -> s -> StateT s m a -> m (a, s)
forall a b c. (a -> b -> c) -> b -> a -> c
flip StateT s m a -> s -> m (a, s)
forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
runStateT s
s (StateT s m a -> m (a, s))
-> (Via (State' tag s) (StateT s) m a -> StateT s m a)
-> Via (State' tag s) (StateT s) m a
-> m (a, s)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Via (State' tag s) (StateT s) m a -> StateT s m a
forall (effs :: [Effect]) (t :: Transformer) (m :: * -> *) a.
EachVia effs t m a -> t m a
runVia
{-# INLINE execState' #-}

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

execState :: Functor m => s -> (State s `Via` StateT s) m a -> m s
execState :: s -> Via (State s) (StateT s) m a -> m s
execState = forall k (tag :: k) s (m :: * -> *) a.
Functor m =>
s -> Via (State' tag s) (StateT s) m a -> m s
forall s (m :: * -> *) a.
Functor m =>
s -> Via (State' G s) (StateT s) m a -> m s
execState' @G
{-# INLINE execState #-}

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

runState' :: forall tag s m a. Functor m
          => s                                 -- ^ The initial state.

          -> (State' tag s `Via` StateT s) m a -- ^ The program whose state effect should be handled.

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

runState' :: s -> Via (State' tag s) (StateT s) m a -> m (s, a)
runState' s :: s
s = ((a, s) -> (s, a)) -> m (a, s) -> m (s, a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a, s) -> (s, a)
forall a b. (a, b) -> (b, a)
swap (m (a, s) -> m (s, a))
-> (Via (State' tag s) (StateT s) m a -> m (a, s))
-> Via (State' tag s) (StateT s) m a
-> m (s, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (StateT s m a -> s -> m (a, s)) -> s -> StateT s m a -> m (a, s)
forall a b c. (a -> b -> c) -> b -> a -> c
flip StateT s m a -> s -> m (a, s)
forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
runStateT s
s (StateT s m a -> m (a, s))
-> (Via (State' tag s) (StateT s) m a -> StateT s m a)
-> Via (State' tag s) (StateT s) m a
-> m (a, s)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Via (State' tag s) (StateT s) m a -> StateT s m a
forall (effs :: [Effect]) (t :: Transformer) (m :: * -> *) a.
EachVia effs t m a -> t m a
runVia
{-# INLINE runState' #-}

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

runState :: Functor m => s -> (State s `Via` StateT s) m a -> m (s, a)
runState :: s -> Via (State s) (StateT s) m a -> m (s, a)
runState = forall k (tag :: k) s (m :: * -> *) a.
Functor m =>
s -> Via (State' tag s) (StateT s) m a -> m (s, a)
forall s (m :: * -> *) a.
Functor m =>
s -> Via (State' G s) (StateT s) m a -> m (s, a)
runState' @G
{-# INLINE runState #-}