@@ -35,7 +35,19 @@ import Effectful.Internal.Has
36type role Env nominal
36type role Env nominal
38+-- | A mutable, strict (elements are kept in weak head normal form), extensible
38−-- | A mutable, extensible record indexed by effect data types.
39+-- record indexed by effect data types.
41+-- Offers pretty much perfect performance characteristics:
43+-- - Extending: /O(1)/ (amortized).
45+-- - Shrinking: /O(1)/.
47+-- - Indexing via '(:>)': /O(1)/ (amortized).
49+-- - Modification of a specific element: /O(1)/.
39newtype Env (es :: [Effect]) = Env (IORef EnvRef)
51newtype Env (es :: [Effect]) = Env (IORef EnvRef)
41data EnvRef = EnvRef Int (SmallMutableArray RealWorld Any)
53data EnvRef = EnvRef Int (SmallMutableArray RealWorld Any)
@@ -90,6 +102,9 @@ unsafeConsEnv e (Env ref) = do
90 e `seq` writeSmallArray es n (toAny e)
102 e `seq` writeSmallArray es n (toAny e)
91 writeIORef ref $! EnvRef (n + 1) es
103 writeIORef ref $! EnvRef (n + 1) es
92 pure $ Env ref
104 pure $ Env ref
106+ doubleCapacity :: Int -> Int
107+ doubleCapacity n = max 1 n * 2
93{-# NOINLINE unsafeConsEnv #-}
108{-# NOINLINE unsafeConsEnv #-}
95-- | Shrink the environment by one data type (in place). Makes sure the size of
110-- | Shrink the environment by one data type (in place). Makes sure the size of
@@ -145,9 +160,6 @@ unsafeStateEnv f (Env ref) = do
145----------------------------------------
160----------------------------------------
146-- Internal helpers
161-- Internal helpers
148−doubleCapacity :: Int -> Int
149−doubleCapacity n = max 1 n * 2
151toAny :: a -> Any
163toAny :: a -> Any
152toAny = unsafeCoerce
164toAny = unsafeCoerce