{-# LANGUAGE TemplateHaskell #-}
module Polysemy.Floodgate
  ( 
    Floodgate (..)
    
  , hold
  , release
    
  , runFloodgate
  , runFloodgateDry
  ) where
import Control.Monad
import GHC.Types
import Polysemy
import Polysemy.State
import Unsafe.Coerce
data Floodgate m a where
  Hold    :: m () -> Floodgate m ()
  Release :: Floodgate m ()
makeSem ''Floodgate
runFloodgate
    :: Sem (Floodgate ': r) a
    -> Sem r a
runFloodgate = fmap snd . runState @[Any] [] . reinterpretH
  ( \case
      Hold m -> do
        m' <- fmap void $ runT m
        
        
        modify (unsafeCoerce @_ @Any (raise $ runFloodgate m') :)
        getInitialStateT
      Release -> do
        ms' <- gets (fmap unsafeCoerce . reverse)
        sequence_ ms'
        getInitialStateT
  )
runFloodgateDry
    :: Sem (Floodgate ': r) a
    -> Sem r a
runFloodgateDry m = runFloodgate $ m <* release