{-# LANGUAGE TemplateHaskell #-}
module Polysemy.EndState
  (-- * Effect
    EndState(..)

    -- * Actions
  , getEndState

    -- * Interpretations
  , runEndState
  , runEndAtomicState
  ) where

import Polysemy
import Polysemy.Fixpoint
import Polysemy.Reader
import Polysemy.Reader.More

import Polysemy.State
import Polysemy.AtomicState


-----------------------------------------------------------------------------
-- | An effect for getting the end state of a computation in advance.
data EndState s m a where
  GetEndState :: EndState s m s

makeSem ''EndState

-----------------------------------------------------------------------------
-- | Runs an 'EndState' effect by getting the state after the computation
-- has finished, and providing it recursively back to calls of 'getEndState'.
runEndState :: forall s r a
             . (Member (State s) r, Member Fixpoint r)
            => Sem (EndState s ': r) a
            -> Sem r a
runEndState =
    runReaderFixSem (get @s)
  . reinterpret (\GetEndState -> ask)


-----------------------------------------------------------------------------
-- | Like 'runEndState', but for 'AtomicState' rather than 'State'.
runEndAtomicState
  :: forall s r a
   . (Member (AtomicState s) r, Member Fixpoint r)
  => Sem (EndState s ': r) a
  -> Sem r a
runEndAtomicState =
    runReaderFixSem (atomicGet @s)
  . reinterpret (\GetEndState -> ask)