From 0bfb7553c4259dc755d1c67b02c375e765ef7305 Mon Sep 17 00:00:00 2001 From: Andrzej Rybczak Date: Wed, 29 Nov 2023 14:59:08 +0100 Subject: [PATCH] Allow access to handler effects in the local environment --- .../src/Effectful/Dispatch/Dynamic.hs | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/effectful-core/src/Effectful/Dispatch/Dynamic.hs b/effectful-core/src/Effectful/Dispatch/Dynamic.hs index 52ae9a3..81abfb4 100644 --- a/effectful-core/src/Effectful/Dispatch/Dynamic.hs +++ b/effectful-core/src/Effectful/Dispatch/Dynamic.hs @@ -46,14 +46,17 @@ module Effectful.Dispatch.Dynamic , localLiftUnlift , localLiftUnliftIO - -- *** Utils + -- *** Misc + , localSeqHandle , SharedSuffix -- * Re-exports , HasCallStack ) where +import Control.Monad import Control.Monad.IO.Unlift +import Data.Primitive.PrimArray import GHC.Stack (HasCallStack) import GHC.TypeLits @@ -726,7 +729,32 @@ localLiftUnliftIO (LocalEnv les) strategy k = case strategy of ConcUnlift p l -> liftIO $ concUnliftIO les p l $ k unsafeEff_ ---------------------------------------- --- Utils +-- Misc + +localSeqHandle + :: (e :> es, SharedSuffix es handlerEs) + => LocalEnv localEs handlerEs + -> ((forall r. Eff (e : localEs) r -> Eff localEs r) -> Eff es a) + -> Eff es a +localSeqHandle (LocalEnv les) k = unsafeEff $ \es -> do + eles <- copyRef es les + seqUnliftIO eles $ \unlift -> (`unEff` es) $ k $ unsafeEff_ . unlift + +copyRef + :: forall e es localEs. e :> es + => Env es + -> Env localEs + -> IO (Env (e : localEs)) +copyRef (Env hoffset hrefs hstorage) (Env offset refs0 storage) = do + when (hstorage /= storage) $ do + error "storages do not match" + let size = sizeofPrimArray refs0 - offset + i = 2 * reifyIndex @e @es + mrefs <- newPrimArray (size + 2) + copyPrimArray mrefs 0 hrefs (hoffset + i) 2 + copyPrimArray mrefs 2 refs0 offset size + refs <- unsafeFreezePrimArray mrefs + pure $ Env 0 refs storage -- | Require that both effect stacks share an opaque suffix. --