on master help sign in
unsafe{Put,State,Modify}Env are safe
commitc851bda0bd41a66ac7f65ae91ace285a31895334 authorAndrzej Rybczak <andrzej@rybczak.net> dateMon 26 Jul 2021, 15:33 (5 years ago) parent96b2bb3
4 files changed+43−37
effectful-core/src/Effectful/Internal/Env.hs+34−28 effectful-core/src/Effectful/Internal/Monad.hs+5−5 effectful-core/src/Effectful/Writer/Local.hs+2−2 effectful-core/src/Effectful/Writer/Shared.hs+2−2
effectful-core/src/Effectful/Internal/Env.hs+34−28
@@ -9,22 +9,22 @@ module Effectful.Internal.Env
99 , Relinker(..)
1010 , noRelinker
1111
12− -- * Safe operations
12+ -- * Operations
1313 , emptyEnv
1414 , cloneEnv
1515 , forkEnv
1616 , sizeEnv
17− , getEnv
1817 , checkSizeEnv
1918
20− -- * Extending and shrinking
19+ -- ** Extending and shrinking
2120 , unsafeConsEnv
2221 , unsafeTailEnv
2322
24− -- * Data retrieval and update
25− , unsafePutEnv
26− , unsafeModifyEnv
27− , unsafeStateEnv
23+ -- ** Data retrieval and update
24+ , getEnv
25+ , putEnv
26+ , stateEnv
27+ , modifyEnv
2828 ) where
2929
3030import Control.Monad
@@ -322,12 +322,6 @@ sizeEnv (Env (Forks _ baseIx lref _) _ _) = do
322322 pure $ baseIx + n
323323{-# NOINLINE sizeEnv #-}
324324
325−-- | Extract a specific data type from the environment.
326−getEnv :: forall e es handler. e :> es => Env es -> IO (handler e)
327−getEnv env = do
328− (i, es) <- getLocation @e env
329− fromAny <$> readSmallArray es i
330−
331325-- | Check that the size of the environment is the same as the expected value.
332326checkSizeEnv :: Int -> Env es -> IO ()
333327checkSizeEnv k (Env NoFork ref _) = do
@@ -345,6 +339,9 @@ checkSizeEnv k (Env (Forks _ baseIx lref _) _ _) = do
345339-- Extending and shrinking
346340
347341-- | Extend the environment with a new data type (in place).
342+--
343+-- /Note:/ this function is __unsafe__ because it renders the input 'Env'
344+-- unusable, but it's not checked anywhere.
348345unsafeConsEnv :: handler e -> Relinker handler e -> Env es -> IO (Env (e : es))
349346unsafeConsEnv e f (Env fork gref gen) = case fork of
350347 NoFork -> do
@@ -380,6 +377,9 @@ unsafeConsEnv e f (Env fork gref gen) = case fork of
380377
381378-- | Shrink the environment by one data type (in place). Makes sure the size of
382379-- the environment is as expected.
380+--
381+-- /Note:/ this function is __unsafe__ because it renders the input 'Env'
382+-- unusable, but it's not checked anywhere.
383383unsafeTailEnv :: Int -> Env (e : es) -> IO (Env es)
384384unsafeTailEnv len (Env fork gref gen) = case fork of
385385 NoFork -> do
@@ -403,39 +403,45 @@ unsafeTailEnv len (Env fork gref gen) = case fork of
403403----------------------------------------
404404-- Data retrieval and update
405405
406−-- | Replace the data type in the environment with a new value (in place).
407−unsafePutEnv
408− :: forall e es handler. e :> es
409− => Env es
410− -> handler e
411− -> IO ()
412−unsafePutEnv env e = do
406+-- | Extract a specific data type from the environment.
407+getEnv :: forall e es handler. e :> es => Env es -> IO (handler e)
408+getEnv env = do
413409 (i, es) <- getLocation @e env
414− e `seq` writeSmallArray es i (toAny e)
410+ fromAny <$> readSmallArray es i
415411
416−-- | Modify the data type in the environment (in place).
417−unsafeModifyEnv
412+-- | Replace the data type in the environment with a new value (in place).
413+putEnv
418414 :: forall e es handler. e :> es
419415 => Env es
420− -> (handler e -> handler e)
416+ -> handler e
421417 -> IO ()
422−unsafeModifyEnv env f = do
418+putEnv env e = do
423419 (i, es) <- getLocation @e env
424− e <- f . fromAny <$> readSmallArray es i
425420 e `seq` writeSmallArray es i (toAny e)
426421
427422-- | Modify the data type in the environment (in place) and return a value.
428−unsafeStateEnv
423+stateEnv
429424 :: forall e es handler a. e :> es
430425 => Env es
431426 -> (handler e -> (a, handler e))
432427 -> IO a
433−unsafeStateEnv env f = do
428+stateEnv env f = do
434429 (i, es) <- getLocation @e env
435430 (a, e) <- f . fromAny <$> readSmallArray es i
436431 e `seq` writeSmallArray es i (toAny e)
437432 pure a
438433
434+-- | Modify the data type in the environment (in place).
435+modifyEnv
436+ :: forall e es handler. e :> es
437+ => Env es
438+ -> (handler e -> handler e)
439+ -> IO ()
440+modifyEnv env f = do
441+ (i, es) <- getLocation @e env
442+ e <- f . fromAny <$> readSmallArray es i
443+ e `seq` writeSmallArray es i (toAny e)
444+
439445----------------------------------------
440446-- Internal helpers
441447
effectful-core/src/Effectful/Internal/Monad.hs+5−5
@@ -432,19 +432,19 @@ getEffect :: e :> es => Eff es (handler e)
432432getEffect = unsafeEff $ \es -> getEnv es
433433
434434putEffect :: e :> es => handler e -> Eff es ()
435−putEffect e = unsafeEff $ \es -> unsafePutEnv es e
435+putEffect e = unsafeEff $ \es -> putEnv es e
436436
437437stateEffect :: e :> es => (handler e -> (a, handler e)) -> Eff es a
438−stateEffect f = unsafeEff $ \es -> unsafeStateEnv es f
438+stateEffect f = unsafeEff $ \es -> stateEnv es f
439439
440440stateEffectM :: e :> es => (handler e -> Eff es (a, handler e)) -> Eff es a
441441stateEffectM f = unsafeEff $ \es -> mask $ \release -> do
442442 (a, e) <- (\e -> release $ unEff (f e) es) =<< getEnv es
443− unsafePutEnv es e
443+ putEnv es e
444444 pure a
445445
446446localEffect :: e :> es => (handler e -> handler e) -> Eff es a -> Eff es a
447447localEffect f m = unsafeEff $ \es -> do
448− bracket (unsafeStateEnv es $ \e -> (e, f e))
449− (\e -> unsafePutEnv es e)
448+ bracket (stateEnv es $ \e -> (e, f e))
449+ (\e -> putEnv es e)
450450 (\_ -> unEff m es)
effectful-core/src/Effectful/Writer/Local.hs+2−2
@@ -34,13 +34,13 @@ tell w = stateEffect $ \(IdE (Writer w0)) -> ((), IdE (Writer (w0 <> w)))
3434
3535listen :: (Writer w :> es, Monoid w) => Eff es a -> Eff es (a, w)
3636listen m = unsafeEff $ \es -> mask $ \restore -> do
37− w0 <- unsafeStateEnv es $ \(IdE (Writer w)) -> (w, IdE (Writer mempty))
37+ w0 <- stateEnv es $ \(IdE (Writer w)) -> (w, IdE (Writer mempty))
3838 a <- restore (unEff m es) `onException` merge es w0
3939 (a, ) <$> merge es w0
4040 where
4141 merge es w0 =
4242 -- If an exception is thrown, restore w0 and keep parts of w1.
43− unsafeStateEnv es $ \(IdE (Writer w1)) -> (w1, IdE (Writer (w0 <> w1)))
43+ stateEnv es $ \(IdE (Writer w1)) -> (w1, IdE (Writer (w0 <> w1)))
4444
4545listens :: (Writer w :> es, Monoid w) => (w -> b) -> Eff es a -> Eff es (a, b)
4646listens f m = do
effectful-core/src/Effectful/Writer/Shared.hs+2−2
@@ -43,14 +43,14 @@ listen m = unsafeEff $ \es -> do
4343 uninterruptibleMask $ \restore -> do
4444 v1 <- newMVar mempty
4545 -- Replace thread local MVar with a fresh one for isolated listening.
46− v0 <- unsafeStateEnv es $ \(IdE (Writer v)) -> (v, IdE (Writer v1))
46+ v0 <- stateEnv es $ \(IdE (Writer v)) -> (v, IdE (Writer v1))
4747 a <- restore (unEff m es) `onException` merge es v0 v1
4848 (a, ) <$> merge es v0 v1
4949 where
5050 -- Merge results accumulated in the local MVar with the mainline. If an
5151 -- exception was received while listening, merge results recorded so far.
5252 merge es v0 v1 = do
53− unsafePutEnv es $ IdE (Writer v0)
53+ putEnv es $ IdE (Writer v0)
5454 w1 <- readMVar v1
5555 modifyMVar_ v0 $ \w0 -> let w = w0 <> w1 in w `seq` pure w
5656 pure w1