{-# OPTIONS_GHC -fplugin=Effectful.Plugin #-}
import Effectful
import Effectful.State.Static.Shared
import Effectful.Concurrent (runConcurrent)
import Effectful.Concurrent.MVar
import Control.Monad (replicateM)
action :: (State Int :> es, IOE :> es) => Eff es Int
action = do
modify (+1)
n <- get
liftIO $ print n
return n
magic :: (forall a. Eff es a -> IO a) -> Eff es b -> IO (IO b)
magic _ = undefined
actionMagic :: IO (IO Int)
actionMagic = magic runEff $ evalState 0 action
actionMVar :: IO (IO Int)
actionMVar = runEff $ runConcurrent $ do
mvar <- newMVar 0
return $ runEff $ evalStateMVar mvar action
main :: IO ()
main = do
action' <- actionMVar
replicateM 5 action' >>= print
-- output:
-- 1
-- 2
-- 3
-- 4
-- 5
-- [1,2,3,4,5]
I have an action with side effects that is wrapped in the Eff monad. How to restore the side effect so that when this action is called multiple times, the state is continued? Can such a “magic” function be implemented for all the possible effect rows (that include IOE, maybe)? Will unliftio help?