@@ -23,6 +23,10 @@ module Effectful.Internal.Monad
2323 , IOE
2424 , runIOE
2525
26+ -- * Primitive
27+ , PrimE
28+ , runPrimE
29+
2630 -- ** Unlift strategies
2731 , UnliftStrategy(..)
2832 , Persistence(..)
@@ -57,9 +61,11 @@ import Control.Monad.Base
5761import Control.Monad.Fix
5862import Control.Monad.IO.Class
5963import Control.Monad.IO.Unlift
64+import Control.Monad.Primitive
6065import Control.Monad.Trans.Control
6166import Data.Unique
6267import GHC.Exts (oneShot)
68+import GHC.IO (IO(..))
6369import System.IO.Unsafe (unsafeDupablePerformIO)
6470import qualified Control.Monad.Catch as E
6571
@@ -95,6 +101,7 @@ type role Eff nominal representational
95101-- perform other effects, and it also allows the effects to be handled in any
96102-- order.
97103newtype Eff (es :: [Effect]) a = Eff (Env es -> IO a)
104+ deriving (Monoid, Semigroup)
98105
99106-- | Run a pure 'Eff' operation.
100107--
@@ -272,6 +279,21 @@ instance IOE :> es => MonadBaseControl IO (Eff es) where
272279instance IOE :> es => MonadUnliftIO (Eff es) where
273280 withRunInIO = unliftEff
274281
282+----------------------------------------
283+-- Primitive
284+
285+-- | An effect to perform primitive state-transformer actions.
286+data PrimE :: Effect where
287+ PrimE :: PrimE m r
288+
289+-- | Run an 'Eff' operation with primitive state-transformer actions.
290+runPrimE :: IOE :> es => Eff (PrimE : es) a -> Eff es a
291+runPrimE = evalEffect (IdE PrimE)
292+
293+instance PrimE :> es => PrimMonad (Eff es) where
294+ type PrimState (Eff es) = PrimState IO
295+ primitive = unsafeEff_ . IO
296+
275297----------------------------------------
276298-- Unlift strategies
277299