diff --git a/aztecs.cabal b/aztecs.cabal
--- a/aztecs.cabal
+++ b/aztecs.cabal
@@ -1,6 +1,6 @@
 cabal-version: 2.4
 name:          aztecs
-version:       0.9.0
+version:       0.9.1
 license:       BSD-3-Clause
 license-file:  LICENSE
 maintainer:    matt@hunzinger.me
diff --git a/src/Aztecs/Asset/AssetLoader.hs b/src/Aztecs/Asset/AssetLoader.hs
--- a/src/Aztecs/Asset/AssetLoader.hs
+++ b/src/Aztecs/Asset/AssetLoader.hs
@@ -38,21 +38,21 @@
 import Data.IORef
 import qualified Data.Map.Strict as Map
 
--- | @since 9.0
+-- | @since 0.9
 type AssetLoader a o = AssetLoaderT a Identity o
 
 -- | Asset loader monad.
 --
--- @since 9.0
+-- @since 0.9
 newtype AssetLoaderT a m o = AssetLoaderT
   { -- | State of the asset loader.
     --
-    -- @since 9.0
+    -- @since 0.9
     unAssetLoader :: StateT (AssetServer a) m o
   }
   deriving newtype (Functor, Applicative, Monad)
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m, Asset a) => MonadAssetLoader a (AssetLoaderT a m) where
   asset path cfg = AssetLoaderT $ do
     server <- get
@@ -72,7 +72,7 @@
 
 -- | Query to load assets.
 --
--- @since 9.0
+-- @since 0.9
 loadQuery :: (Asset a, ArrowQuery m arr) => AssetLoader a o -> arr () o
 loadQuery a = proc () -> do
   server <- Q.fetch -< ()
@@ -82,6 +82,6 @@
 
 -- | System to load assets.
 --
--- @since 9.0
+-- @since 0.9
 load :: forall m q s a o. (ArrowQuery m q, MonadSystem q s, Asset a) => AssetLoader a o -> s o
 load a = S.mapSingle @q () $ loadQuery a
diff --git a/src/Aztecs/Asset/AssetLoader/Class.hs b/src/Aztecs/Asset/AssetLoader/Class.hs
--- a/src/Aztecs/Asset/AssetLoader/Class.hs
+++ b/src/Aztecs/Asset/AssetLoader/Class.hs
@@ -15,9 +15,9 @@
 
 -- | Monadic interface for loading assets.
 --
--- @since 9.0
+-- @since 0.9
 class MonadAssetLoader a m | m -> a where
   -- | Load an asset from a file path with a configuration.
   --
-  -- @since 9.0
+  -- @since 0.9
   asset :: FilePath -> AssetConfig a -> m (Handle a)
diff --git a/src/Aztecs/Asset/AssetServer.hs b/src/Aztecs/Asset/AssetServer.hs
--- a/src/Aztecs/Asset/AssetServer.hs
+++ b/src/Aztecs/Asset/AssetServer.hs
@@ -40,44 +40,44 @@
 
 -- | Unique identifier for an asset.
 --
--- @since 9.0
+-- @since 0.9
 newtype AssetId = AssetId
   { -- | Unique integer identifier.
     --
-    -- @since 9.0
+    -- @since 0.9
     unAssetId :: Int
   }
   deriving (Eq, Ord, Show)
 
 -- | Asset server.
 --
--- @since 9.0
+-- @since 0.9
 data AssetServer a = AssetServer
   { -- | Loaded assets.
     --
-    -- @since 9.0
+    -- @since 0.9
     assetServerAssets :: !(Map AssetId a),
     -- | Assets currently being loaded.
     --
-    -- @since 9.0
+    -- @since 0.9
     loadingAssets :: !(Map AssetId (Either (IO (IORef (Maybe a))) (IORef (Maybe a)))),
     -- | Next unique asset identifier.
     --
-    -- @since 9.0
+    -- @since 0.9
     nextAssetId :: !AssetId
   }
   deriving (Generic)
 
--- | @since 9.0
+-- | @since 0.9
 instance (Typeable a) => Component (AssetServer a)
 
--- | @since 9.0
+-- | @since 0.9
 instance NFData (AssetServer a) where
   rnf = rwhnf
 
 -- | Empty asset server.
 --
--- @since 9.0
+-- @since 0.9
 assetServer :: AssetServer a
 assetServer =
   AssetServer
@@ -88,40 +88,40 @@
 
 -- | Handle to an asset.
 --
--- @since 9.0
+-- @since 0.9
 newtype Handle a = Handle
   { -- | Asset ID.
     --
-    -- @since 9.0
+    -- @since 0.9
     handleId :: AssetId
   }
   deriving (Eq, Ord, Show)
 
--- | @since 9.0
+-- | @since 0.9
 instance NFData (Handle a) where
   rnf = rwhnf
 
 -- | Lookup an asset by its handle.
 --
--- @since 9.0
+-- @since 0.9
 lookupAsset :: Handle a -> AssetServer a -> Maybe a
 lookupAsset h server = Map.lookup (handleId h) (assetServerAssets server)
 
 -- | Setup the asset server.
 --
--- @since 9.0
+-- @since 0.9
 setup :: forall m b a. (Typeable a, MonadAccess b m) => m ()
 setup = A.spawn_ . bundle $ assetServer @a
 
 -- | Load any pending assets.
 --
--- @since 9.0
+-- @since 0.9
 loadAssets :: forall a q s m. (Typeable a, ArrowQuery m q, MonadSystem q s, MonadIO m) => s ()
 loadAssets = void . S.map @q () $ Q.adjustM (\_ s -> loadAssetServer @m @a s)
 
 -- | Load any pending assets in an `AssetServer`.
 --
--- @since 9.0
+-- @since 0.9
 loadAssetServer :: (MonadIO m) => AssetServer a -> m (AssetServer a)
 loadAssetServer server =
   let go (aId, v) acc = do
diff --git a/src/Aztecs/Asset/Class.hs b/src/Aztecs/Asset/Class.hs
--- a/src/Aztecs/Asset/Class.hs
+++ b/src/Aztecs/Asset/Class.hs
@@ -14,14 +14,14 @@
 
 -- | Loadable asset.
 --
--- @since 9.0
+-- @since 0.9
 class (Typeable a) => Asset a where
   -- | Configuration for loading an asset.
   --
-  -- @since 9.0
+  -- @since 0.9
   type AssetConfig a
 
   -- | Load an asset from a file path with a configuration.
   --
-  -- @since 9.0
+  -- @since 0.9
   loadAsset :: FilePath -> AssetConfig a -> IO a
diff --git a/src/Aztecs/Camera.hs b/src/Aztecs/Camera.hs
--- a/src/Aztecs/Camera.hs
+++ b/src/Aztecs/Camera.hs
@@ -29,39 +29,39 @@
 
 -- | Camera component.
 --
--- @since 9.0
+-- @since 0.9
 data Camera = Camera
   { -- | Camera viewport size.
     --
-    -- @since 9.0
+    -- @since 0.9
     cameraViewport :: !(V2 Int),
     -- | Camera scale factor.
     --
-    -- @since 9.0
+    -- @since 0.9
     cameraScale :: !(V2 Float)
   }
   deriving (Show, Generic, NFData)
 
--- | @since 9.0
+-- | @since 0.9
 instance Component Camera
 
 -- | Camera target component.
 --
--- @since 9.0
+-- @since 0.9
 newtype CameraTarget = CameraTarget
   { -- | This camera's target window.
     --
-    -- @since 9.0
+    -- @since 0.9
     cameraTargetWindow :: EntityID
   }
   deriving (Eq, Show, Generic, NFData)
 
--- | @since 9.0
+-- | @since 0.9
 instance Component CameraTarget
 
 -- | Add `CameraTarget` components to entities with a new `Draw` component.
 --
--- @since 9.0
+-- @since 0.9
 addCameraTargets ::
   ( ArrowQueryReader qr,
     ArrowDynamicQueryReader qr,
diff --git a/src/Aztecs/ECS/Access.hs b/src/Aztecs/ECS/Access.hs
--- a/src/Aztecs/ECS/Access.hs
+++ b/src/Aztecs/ECS/Access.hs
@@ -44,16 +44,16 @@
 import Control.Monad.State.Strict
 import qualified Data.Foldable as F
 
--- | @since 9.0
+-- | @since 0.9
 type Access = AccessT Identity
 
 -- | Access into the `World`.
 --
--- @since 9.0
+-- @since 0.9
 newtype AccessT m a = AccessT {unAccessT :: StateT World m a}
   deriving (Functor, Applicative, MonadFix, MonadIO)
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => Monad (AccessT m) where
   a >>= f = AccessT $ do
     !w <- get
@@ -63,17 +63,17 @@
 
 -- | Run an `Access` on a `World`, returning the output and updated `World`.
 --
--- @since 9.0
+-- @since 0.9
 runAccessT :: (Functor m) => AccessT m a -> World -> m (a, World)
 runAccessT a = runStateT $ unAccessT a
 
 -- | Run an `Access` on an empty `World`.
 --
--- @since 9.0
+-- @since 0.9
 runAccessT_ :: (Functor m) => AccessT m a -> m a
 runAccessT_ a = fmap fst . runAccessT a $ W.empty
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => MonadAccess Bundle (AccessT m) where
   spawn b = AccessT $ do
     !w <- get
@@ -97,7 +97,7 @@
     let !(_, w') = W.despawn e w
     put w'
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => MonadReaderSystem (QueryReaderT m) (AccessT m) where
   all i q = AccessT $ do
     w <- get
@@ -114,7 +114,7 @@
             && F.all (\cId -> not (A.member cId $ nodeArchetype n)) (filterWithout dynF)
     unAccessT $ filterDyn i cIds dynQ f'
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => MonadSystem (QueryT m) (AccessT m) where
   map i q = AccessT $ do
     !w <- get
@@ -136,7 +136,7 @@
             && F.all (\cId -> not (A.member cId $ nodeArchetype n)) (filterWithout dynF)
     unAccessT $ filterMapDyn i (Q.reads rws <> Q.writes rws) f' dynQ
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => MonadDynamicReaderSystem (DynamicQueryReaderT m) (AccessT m) where
   allDyn i cIds q = AccessT $ do
     !w <- get
@@ -145,7 +145,7 @@
     !w <- get
     lift . Q.filterDyn cIds i f q $ entities w
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => MonadDynamicSystem (DynamicQueryT m) (AccessT m) where
   mapDyn i cIds q = AccessT $ do
     !w <- get
@@ -165,7 +165,7 @@
 
 -- | Run a `System`.
 --
--- @since 9.0
+-- @since 0.9
 system :: System a -> AccessT IO a
 system s = AccessT $ do
   !w <- get
diff --git a/src/Aztecs/ECS/Access/Class.hs b/src/Aztecs/ECS/Access/Class.hs
--- a/src/Aztecs/ECS/Access/Class.hs
+++ b/src/Aztecs/ECS/Access/Class.hs
@@ -16,16 +16,16 @@
 
 -- | Monadic access to a `World`.
 --
--- @since 9.0
+-- @since 0.9
 class (MonoidBundle b, Monad m) => MonadAccess b m | m -> b where
   -- | Spawn an entity with a component.
   --
-  -- @since 9.0
+  -- @since 0.9
   spawn :: b -> m EntityID
 
   -- | Spawn an entity with a component.
   --
-  -- @since 9.0
+  -- @since 0.9
   spawn_ :: b -> m ()
   spawn_ c = do
     _ <- spawn c
@@ -33,20 +33,20 @@
 
   -- | Insert a component into an entity.
   --
-  -- @since 9.0
+  -- @since 0.9
   insert :: EntityID -> b -> m ()
 
   -- | Lookup a component on an entity.
   --
-  -- @since 9.0
+  -- @since 0.9
   lookup :: (Component a) => EntityID -> m (Maybe a)
 
   -- | Remove a component from an entity.
   --
-  -- @since 9.0
+  -- @since 0.9
   remove :: (Component a) => EntityID -> m (Maybe a)
 
   -- | Despawn an entity.
   --
-  -- @since 9.0
+  -- @since 0.9
   despawn :: EntityID -> m ()
diff --git a/src/Aztecs/ECS/Component.hs b/src/Aztecs/ECS/Component.hs
--- a/src/Aztecs/ECS/Component.hs
+++ b/src/Aztecs/ECS/Component.hs
@@ -20,22 +20,22 @@
 
 -- | Unique component identifier.
 --
--- @since 9.0
+-- @since 0.9
 newtype ComponentID = ComponentID
   { -- | Unique integer identifier.
     --
-    -- @since 9.0
+    -- @since 0.9
     unComponentId :: Int
   }
   deriving (Eq, Ord, Show, Generic, NFData)
 
 -- | Component that can be stored in the `World`.
 --
--- @since 9.0
+-- @since 0.9
 class (Typeable a, Storage a (StorageT a)) => Component a where
   -- | `Storage` of this component.
   --
-  -- @since 9.0
+  -- @since 0.9
   type StorageT a
 
   type StorageT a = [a]
diff --git a/src/Aztecs/ECS/Entity.hs b/src/Aztecs/ECS/Entity.hs
--- a/src/Aztecs/ECS/Entity.hs
+++ b/src/Aztecs/ECS/Entity.hs
@@ -16,11 +16,11 @@
 
 -- | Unique entity identifier.
 --
--- @since 9.0
+-- @since 0.9
 newtype EntityID = EntityID
   { -- | Unique integer identifier.
     --
-    -- @since 9.0
+    -- @since 0.9
     unEntityId :: Int
   }
   deriving (Eq, Ord, Show, Generic, NFData)
diff --git a/src/Aztecs/ECS/Query.hs b/src/Aztecs/ECS/Query.hs
--- a/src/Aztecs/ECS/Query.hs
+++ b/src/Aztecs/ECS/Query.hs
@@ -86,21 +86,21 @@
 import GHC.Stack
 import Prelude hiding (all, id, map, reads, (.))
 
--- | @since 9.0
+-- | @since 0.9
 type Query i = QueryT Identity i
 
 -- | Query for matching entities.
 --
--- @since 9.0
+-- @since 0.9
 newtype QueryT m i o = Query
   { -- | Run a query, producing a `DynamicQueryT`.
     --
-    -- @since 9.0
+    -- @since 0.9
     runQuery :: Components -> (ReadsWrites, Components, DynamicQueryT m i o)
   }
   deriving (Functor)
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => Applicative (QueryT m i) where
   {-# INLINE pure #-}
   pure a = Query (mempty,,pure a)
@@ -110,7 +110,7 @@
         !(cIdsF, cs'', bQS) = f cs'
      in (cIdsG <> cIdsF, cs'', bQS <*> aQS)
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => Category (QueryT m) where
   {-# INLINE id #-}
   id = Query (mempty,,id)
@@ -120,26 +120,26 @@
         !(cIdsF, cs'', bQS) = f cs'
      in (cIdsG <> cIdsF, cs'', bQS . aQS)
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => Arrow (QueryT m) where
   {-# INLINE arr #-}
   arr f = Query (mempty,,arr f)
   {-# INLINE first #-}
   first (Query f) = Query $ \cs -> let !(cIds, cs', qS) = f cs in (cIds, cs', first qS)
 
--- |  @since 9.0
+-- |  @since 0.9
 instance (Monad m) => ArrowChoice (QueryT m) where
   {-# INLINE left #-}
   left (Query f) = Query $ \cs -> let !(cIds, cs', qS) = f cs in (cIds, cs', left qS)
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => ArrowQueryReader (QueryT m) where
   {-# INLINE fetch #-}
   fetch = fromReader fetch
   {-# INLINE fetchMaybe #-}
   fetchMaybe = fromReader fetchMaybe
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => ArrowDynamicQueryReader (QueryT m) where
   {-# INLINE entity #-}
   entity = fromReader entity
@@ -148,7 +148,7 @@
   {-# INLINE fetchMaybeDyn #-}
   fetchMaybeDyn = fromReader . fetchMaybeDyn
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => ArrowDynamicQuery m (QueryT m) where
   {-# INLINE adjustDyn #-}
   adjustDyn f cId = Query (ReadsWrites Set.empty (Set.singleton cId),,adjustDyn f cId)
@@ -159,7 +159,7 @@
   {-# INLINE setDyn #-}
   setDyn cId = Query (ReadsWrites Set.empty (Set.singleton cId),,setDyn cId)
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => ArrowQuery m (QueryT m) where
   {-# INLINE adjust #-}
   adjust :: forall i a. (Component a) => (i -> a -> a) -> QueryT m i a
@@ -179,7 +179,7 @@
 
 -- | Convert a `DynamicQueryT` to a `Query`.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE fromDyn #-}
 fromDyn :: forall a m i o. (Component a) => (ComponentID -> DynamicQueryT m i o) -> QueryT m i o
 fromDyn f = Query $ \cs ->
@@ -187,7 +187,7 @@
 
 -- | Convert a `QueryReader` to a `Query`.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE fromReader #-}
 fromReader :: (Monad m) => QueryReaderT m i o -> QueryT m i o
 fromReader (QueryReader f) = Query $ \cs ->
@@ -195,7 +195,7 @@
 
 -- | Convert a `Query` to a `QueryReader`.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE toReader #-}
 toReader :: (Functor m) => QueryT m i o -> QueryReaderT m i o
 toReader (Query f) = QueryReader $ \cs ->
@@ -203,30 +203,30 @@
 
 -- | Reads and writes of a `Query`.
 --
--- @since 9.0
+-- @since 0.9
 data ReadsWrites = ReadsWrites
   { -- | Component IDs being read.
     --
-    -- @since 9.0
+    -- @since 0.9
     reads :: !(Set ComponentID),
     -- | Component IDs being written.
     --
-    -- @since 9.0
+    -- @since 0.9
     writes :: !(Set ComponentID)
   }
   deriving (Show)
 
--- | @since 9.0
+-- | @since 0.9
 instance Semigroup ReadsWrites where
   ReadsWrites r1 w1 <> ReadsWrites r2 w2 = ReadsWrites (r1 <> r2) (w1 <> w2)
 
--- | @since 9.0
+-- | @since 0.9
 instance Monoid ReadsWrites where
   mempty = ReadsWrites mempty mempty
 
 -- | `True` if the reads and writes of two `Query`s overlap.
 --
--- @since 9.0
+-- @since 0.9
 disjoint :: ReadsWrites -> ReadsWrites -> Bool
 disjoint a b =
   Set.disjoint (reads a) (writes b)
@@ -235,49 +235,49 @@
 
 -- | Match all entities.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE all #-}
 all :: (Monad m) => i -> QueryT m i a -> Entities -> (m [a], Entities)
 all i = QR.all i . toReader
 
 -- | Match all entities.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE all' #-}
 all' :: (Monad m) => i -> QueryT m i a -> Entities -> (m [a], Components)
 all' i = QR.all' i . toReader
 
 -- | Match a single entity.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE single #-}
 single :: (HasCallStack) => i -> Query i a -> Entities -> (a, Entities)
 single i = QR.single i . toReader
 
 -- | Match a single entity.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE single' #-}
 single' :: (HasCallStack) => i -> Query i a -> Entities -> (a, Components)
 single' i = QR.single' i . toReader
 
 -- | Match a single entity, or `Nothing`.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE singleMaybe #-}
 singleMaybe :: i -> Query i a -> Entities -> (Maybe a, Entities)
 singleMaybe i = QR.singleMaybe i . toReader
 
 -- | Match a single entity, or `Nothing`.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE singleMaybe' #-}
 singleMaybe' :: i -> Query i a -> Entities -> (Maybe a, Components)
 singleMaybe' i = QR.singleMaybe' i . toReader
 
 -- | Map all matched entities.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE map #-}
 map :: (Monad m) => i -> QueryT m i o -> Entities -> m ([o], Entities)
 map i q es = do
@@ -288,7 +288,7 @@
 
 -- | Map a single matched entity.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE mapSingle #-}
 mapSingle :: (HasCallStack, Monad m) => i -> QueryT m i a -> Entities -> m (a, Entities)
 mapSingle i q es = do
@@ -299,7 +299,7 @@
 
 -- | Map a single matched entity, or `Nothing`.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE mapSingleMaybe #-}
 mapSingleMaybe :: (Monad m) => i -> QueryT m i a -> Entities -> m (Maybe a, Entities)
 mapSingleMaybe i q es = do
diff --git a/src/Aztecs/ECS/Query/Class.hs b/src/Aztecs/ECS/Query/Class.hs
--- a/src/Aztecs/ECS/Query/Class.hs
+++ b/src/Aztecs/ECS/Query/Class.hs
@@ -19,25 +19,25 @@
 
 -- | Arrow for queries that can update entities.
 --
--- @since 9.0
+-- @since 0.9
 class (ArrowQueryReader arr) => ArrowQuery m arr | arr -> m where
   -- | Adjust a `Component` by its type.
   --
-  -- @since 9.0
+  -- @since 0.9
   adjust :: (Component a) => (i -> a -> a) -> arr i a
 
   -- | Adjust a `Component` by its type, ignoring any output.
   --
-  -- @since 9.0
+  -- @since 0.9
   adjust_ :: (Component a) => (i -> a -> a) -> arr i ()
   adjust_ f = adjust @m f >>> arr (const ())
 
   -- | Adjust a `Component` by its type with some `Monad` @m@.
   --
-  -- @since 9.0
+  -- @since 0.9
   adjustM :: (Component a) => (i -> a -> m a) -> arr i a
 
   -- | Set a `Component` by its type.
   --
-  -- @since 9.0
+  -- @since 0.9
   set :: (Component a) => arr a a
diff --git a/src/Aztecs/ECS/Query/Dynamic.hs b/src/Aztecs/ECS/Query/Dynamic.hs
--- a/src/Aztecs/ECS/Query/Dynamic.hs
+++ b/src/Aztecs/ECS/Query/Dynamic.hs
@@ -53,23 +53,23 @@
 import GHC.Stack (HasCallStack)
 import Prelude hiding ((.))
 
--- | @since 9.0
+-- | @since 0.9
 type DynamicQuery = DynamicQueryT Identity
 
 -- | Dynamic query for components by ID.
 --
--- @since 9.0
+-- @since 0.9
 newtype DynamicQueryT m i o
   = DynamicQuery
   { -- | Run a dynamic query with a list of inputs with length equal to the number of entities in the `Archetype`.
     -- This is an internal function that should typically not be used directly.
     --
-    -- @since 9.0
+    -- @since 0.9
     runDynQuery :: [i] -> Archetype -> m ([o], Archetype)
   }
   deriving (Functor)
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => Applicative (DynamicQueryT m i) where
   {-# INLINE pure #-}
   pure a = DynamicQuery $ \is arch -> pure (replicate (length is) a, arch)
@@ -79,7 +79,7 @@
     (fs, arch'') <- runDynQuery f i arch'
     return (zipWith ($) fs as, arch'')
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => Category (DynamicQueryT m) where
   {-# INLINE id #-}
   id = DynamicQuery $ curry pure
@@ -88,7 +88,7 @@
     (as, arch') <- runDynQuery g i arch
     runDynQuery f as arch'
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => Arrow (DynamicQueryT m) where
   {-# INLINE arr #-}
   arr f = DynamicQuery $ \bs arch -> pure (fmap f bs, arch)
@@ -98,7 +98,7 @@
     (cs, arch') <- runDynQuery f bs arch
     return (zip cs ds, arch')
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => ArrowChoice (DynamicQueryT m) where
   {-# INLINE left #-}
   left f = DynamicQuery $ \eds arch -> do
@@ -106,7 +106,7 @@
     (cs, arch') <- runDynQuery f es' arch
     return (fmap Left cs ++ fmap Right ds, arch')
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => ArrowDynamicQueryReader (DynamicQueryT m) where
   {-# INLINE entity #-}
   entity = fromDynReader entity
@@ -115,7 +115,7 @@
   {-# INLINE fetchMaybeDyn #-}
   fetchMaybeDyn = fromDynReader . fetchMaybeDyn
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => ArrowDynamicQuery m (DynamicQueryT m) where
   {-# INLINE adjustDyn #-}
   adjustDyn f cId = DynamicQuery $ \is arch -> pure $ A.zipWith is f cId arch
@@ -131,7 +131,7 @@
 
 -- | Convert a `DynamicQueryReaderT` to a `DynamicQueryT`.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE fromDynReader #-}
 fromDynReader :: (Monad m) => DynamicQueryReaderT m i o -> DynamicQueryT m i o
 fromDynReader q = DynamicQuery $ \is arch -> do
@@ -140,14 +140,14 @@
 
 -- | Convert a `DynamicQueryT` to a `DynamicQueryReaderT`.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE toDynReader #-}
 toDynReader :: (Functor m) => DynamicQueryT m i o -> DynamicQueryReaderT m i o
 toDynReader q = DynamicQueryReader $ \is arch -> fst <$> runDynQuery q is arch
 
 -- | Map all matched entities.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE mapDyn #-}
 mapDyn :: (Monad m) => Set ComponentID -> i -> DynamicQueryT m i a -> Entities -> m ([a], Entities)
 mapDyn cIds i q es =
@@ -165,7 +165,7 @@
 
 -- | Map all matched entities.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE filterMapDyn #-}
 filterMapDyn :: (Monad m) => Set ComponentID -> i -> (Node -> Bool) -> DynamicQueryT m i a -> Entities -> m ([a], Entities)
 filterMapDyn cIds i f q es =
@@ -183,7 +183,7 @@
 
 -- | Map a single matched entity.
 --
--- @since 9.0
+-- @since 0.9
 mapSingleDyn :: (HasCallStack, Monad m) => Set ComponentID -> i -> DynamicQueryT m i a -> Entities -> m (a, Entities)
 mapSingleDyn cIds i q es = do
   res <- mapSingleMaybeDyn cIds i q es
@@ -193,7 +193,7 @@
 
 -- | Map a single matched entity, or @Nothing@.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE mapSingleMaybeDyn #-}
 mapSingleMaybeDyn :: (Monad m) => Set ComponentID -> i -> DynamicQueryT m i a -> Entities -> m (Maybe a, Entities)
 mapSingleMaybeDyn cIds i q es =
diff --git a/src/Aztecs/ECS/Query/Dynamic/Class.hs b/src/Aztecs/ECS/Query/Dynamic/Class.hs
--- a/src/Aztecs/ECS/Query/Dynamic/Class.hs
+++ b/src/Aztecs/ECS/Query/Dynamic/Class.hs
@@ -19,25 +19,25 @@
 
 -- | Arrow dynamic query.
 --
--- @since 9.0
+-- @since 0.9
 class (ArrowDynamicQueryReader arr) => ArrowDynamicQuery m arr | arr -> m where
   -- | Adjust a `Component` by its `ComponentID`.
   --
-  -- @since 9.0
+  -- @since 0.9
   adjustDyn :: (Component a) => (i -> a -> a) -> ComponentID -> arr i a
 
   -- | Adjust a `Component` by its `ComponentID`, ignoring any output.
   --
-  -- @since 9.0
+  -- @since 0.9
   adjustDyn_ :: (Component a) => (i -> a -> a) -> ComponentID -> arr i ()
   adjustDyn_ f cid = adjustDyn @m f cid >>> arr (const ())
 
   -- | Adjust a `Component` by its `ComponentID` with some `Monad` @m@.
   --
-  -- @since 9.0
+  -- @since 0.9
   adjustDynM :: (Component a) => (i -> a -> m a) -> ComponentID -> arr i a
 
   -- | Set a `Component` by its `ComponentID`.
   --
-  -- @since 9.0
+  -- @since 0.9
   setDyn :: (Component a) => ComponentID -> arr a a
diff --git a/src/Aztecs/ECS/Query/Dynamic/Reader.hs b/src/Aztecs/ECS/Query/Dynamic/Reader.hs
--- a/src/Aztecs/ECS/Query/Dynamic/Reader.hs
+++ b/src/Aztecs/ECS/Query/Dynamic/Reader.hs
@@ -46,23 +46,23 @@
 import qualified Data.Set as Set
 import GHC.Stack
 
--- | @since 9.0
+-- | @since 0.9
 type DynamicQueryReader = DynamicQueryReaderT Identity
 
 -- | Dynamic query for components by ID.
 --
--- @since 9.0
+-- @since 0.9
 newtype DynamicQueryReaderT m i o
   = DynamicQueryReader
   { -- | Run a dynamic query with a list of inputs with length equal to the number of entities in the `Archetype`.
     -- This is an internal function that should typically not be used directly.
     --
-    -- @since 9.0
+    -- @since 0.9
     runDynQueryReader' :: [i] -> Archetype -> m [o]
   }
   deriving (Functor)
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => Applicative (DynamicQueryReaderT m i) where
   {-# INLINE pure #-}
   pure a = DynamicQueryReader $ \is _ -> pure $ replicate (length is) a
@@ -73,7 +73,7 @@
       !fs <- runDynQueryReader' f i arch
       return $ zipWith ($) fs as
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => Category (DynamicQueryReaderT m) where
   {-# INLINE id #-}
   id = DynamicQueryReader $ \as _ -> pure as
@@ -82,7 +82,7 @@
     !as <- runDynQueryReader' g i arch
     runDynQueryReader' f as arch
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => Arrow (DynamicQueryReaderT m) where
   {-# INLINE arr #-}
   arr f = DynamicQueryReader $ \bs _ -> pure $ fmap f bs
@@ -92,7 +92,7 @@
     !cs <- runDynQueryReader' f bs arch
     return $ zip cs ds
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => ArrowChoice (DynamicQueryReaderT m) where
   {-# INLINE left #-}
   left f = DynamicQueryReader $ \eds arch -> do
@@ -100,7 +100,7 @@
     !cs <- runDynQueryReader' f es' arch
     return $ fmap Left cs ++ fmap Right ds
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => ArrowDynamicQueryReader (DynamicQueryReaderT m) where
   {-# INLINE entity #-}
   entity = DynamicQueryReader $ \_ arch -> pure $ Set.toList $ A.entities arch
@@ -113,44 +113,44 @@
 
 -- | Dynamic query filter.
 --
--- @since 9.0
+-- @since 0.9
 data DynamicQueryFilter = DynamicQueryFilter
   { -- | `ComponentID`s to include.
     --
-    -- @since 9.0
+    -- @since 0.9
     filterWith :: !(Set ComponentID),
     -- | `ComponentID`s to exclude.
     --
-    -- @since 9.0
+    -- @since 0.9
     filterWithout :: !(Set ComponentID)
   }
 
--- | @since 9.0
+-- | @since 0.9
 instance Semigroup DynamicQueryFilter where
   DynamicQueryFilter withA withoutA <> DynamicQueryFilter withB withoutB =
     DynamicQueryFilter (withA <> withB) (withoutA <> withoutB)
 
--- | @since 9.0
+-- | @since 0.9
 instance Monoid DynamicQueryFilter where
   mempty = DynamicQueryFilter mempty mempty
 
 -- | Run a dynamic query.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE runDynQueryReaderT #-}
 runDynQueryReaderT :: i -> DynamicQueryReaderT m i o -> Archetype -> m [o]
 runDynQueryReaderT i q arch = runDynQueryReader' q (replicate (length $ A.entities arch) i) arch
 
 -- | Run a dynamic query.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE runDynQueryReader #-}
 runDynQueryReader :: i -> DynamicQueryReader i o -> Archetype -> [o]
 runDynQueryReader i q arch = runIdentity $ runDynQueryReaderT i q arch
 
 -- | Match all entities.
 --
--- @since 9.0
+-- @since 0.9
 allDyn :: (Monad m) => Set ComponentID -> i -> DynamicQueryReaderT m i a -> Entities -> m [a]
 allDyn cIds i q es =
   if Set.null cIds
@@ -161,7 +161,7 @@
 
 -- | Match all entities with a filter.
 --
--- @since 9.0
+-- @since 0.9
 filterDyn :: (Monad m) => Set ComponentID -> i -> (Node -> Bool) -> DynamicQueryReaderT m i a -> Entities -> m [a]
 filterDyn cIds i f q es =
   if Set.null cIds
@@ -172,7 +172,7 @@
 
 -- | Match a single entity.
 --
--- @since 9.0
+-- @since 0.9
 singleDyn :: (HasCallStack) => Set ComponentID -> i -> DynamicQueryReader i a -> Entities -> a
 singleDyn cIds i q es = case singleMaybeDyn cIds i q es of
   Just a -> a
@@ -180,7 +180,7 @@
 
 -- | Match a single entity, or `Nothing`.
 --
--- @since 9.0
+-- @since 0.9
 singleMaybeDyn :: Set ComponentID -> i -> DynamicQueryReader i a -> Entities -> Maybe a
 singleMaybeDyn cIds i q es =
   if Set.null cIds
diff --git a/src/Aztecs/ECS/Query/Dynamic/Reader/Class.hs b/src/Aztecs/ECS/Query/Dynamic/Reader/Class.hs
--- a/src/Aztecs/ECS/Query/Dynamic/Reader/Class.hs
+++ b/src/Aztecs/ECS/Query/Dynamic/Reader/Class.hs
@@ -14,20 +14,20 @@
 
 -- | Arrow dynamic query reader.
 --
--- @since 9.0
+-- @since 0.9
 class (Arrow arr) => ArrowDynamicQueryReader arr where
   -- | Fetch the currently matched `EntityID`.
   --
-  -- @since 9.0
+  -- @since 0.9
   entity :: arr () EntityID
 
   -- | Fetch a `Component` by its `ComponentID`.
   --
-  -- @since 9.0
+  -- @since 0.9
   fetchDyn :: (Component a) => ComponentID -> arr () a
 
   -- | Try to fetch a `Component` by its `ComponentID`.
   --
-  -- @since 9.0
+  -- @since 0.9
   fetchMaybeDyn :: (Component a) => ComponentID -> arr () (Maybe a)
   fetchMaybeDyn cId = fetchDyn cId >>> arr Just
diff --git a/src/Aztecs/ECS/Query/Reader.hs b/src/Aztecs/ECS/Query/Reader.hs
--- a/src/Aztecs/ECS/Query/Reader.hs
+++ b/src/Aztecs/ECS/Query/Reader.hs
@@ -55,22 +55,22 @@
 import GHC.Stack
 import Prelude hiding (all, id, (.))
 
--- | @since 9.0
+-- | @since 0.9
 type QueryReader = QueryReaderT Identity
 
 -- | Query to read from entities.
 --
--- @since 9.0
+-- @since 0.9
 newtype QueryReaderT m i o
   = QueryReader
   { -- | Run a query reader.
     --
-    -- @since 9.0
+    -- @since 0.9
     runQueryReader :: Components -> (Set ComponentID, Components, DynamicQueryReaderT m i o)
   }
   deriving (Functor)
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => Applicative (QueryReaderT m i) where
   {-# INLINE pure #-}
   pure a = QueryReader (mempty,,pure a)
@@ -80,7 +80,7 @@
         !(cIdsF, cs'', bQS) = f cs'
      in (cIdsG <> cIdsF, cs'', bQS <*> aQS)
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => Category (QueryReaderT m) where
   {-# INLINE id #-}
   id = QueryReader (mempty,,id)
@@ -90,19 +90,19 @@
         !(cIdsF, cs'', bQS) = f cs'
      in (cIdsG <> cIdsF, cs'', bQS . aQS)
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => Arrow (QueryReaderT m) where
   {-# INLINE arr #-}
   arr f = QueryReader (mempty,,arr f)
   {-# INLINE first #-}
   first (QueryReader f) = QueryReader $ \cs -> let !(cIds, comps', qS) = f cs in (cIds, comps', first qS)
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => ArrowChoice (QueryReaderT m) where
   {-# INLINE left #-}
   left (QueryReader f) = QueryReader $ \cs -> let !(cIds, comps', qS) = f cs in (cIds, comps', left qS)
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => ArrowQueryReader (QueryReaderT m) where
   {-# INLINE fetch #-}
   fetch :: forall a. (Component a) => QueryReaderT m () a
@@ -114,7 +114,7 @@
   fetchMaybe = QueryReader $ \cs ->
     let !(cId, cs') = CS.insert @a cs in (Set.singleton cId, cs', fetchMaybeDyn cId)
 
--- | @since 9.0
+-- | @since 0.9
 instance (Monad m) => ArrowDynamicQueryReader (QueryReaderT m) where
   {-# INLINE entity #-}
   entity = QueryReader (mempty,,entity)
@@ -125,13 +125,13 @@
 
 -- | Filter for a `Query`.
 --
--- @since 9.0
+-- @since 0.9
 newtype QueryFilter = QueryFilter
   { -- | Run a query filter.
     runQueryFilter :: Components -> (DynamicQueryFilter, Components)
   }
 
--- | @since 9.0
+-- | @since 0.9
 instance Semigroup QueryFilter where
   a <> b =
     QueryFilter
@@ -141,62 +141,62 @@
            in (withA' <> withB', cs'')
       )
 
--- | @since 9.0
+-- | @since 0.9
 instance Monoid QueryFilter where
   mempty = QueryFilter (mempty,)
 
 -- | Filter for entities containing this component.
 --
--- @since 9.0
+-- @since 0.9
 with :: forall a. (Component a) => QueryFilter
 with = QueryFilter $ \cs ->
   let !(cId, cs') = CS.insert @a cs in (mempty {filterWith = Set.singleton cId}, cs')
 
 -- | Filter out entities containing this component.
 --
--- @since 9.0
+-- @since 0.9
 without :: forall a. (Component a) => QueryFilter
 without = QueryFilter $ \cs ->
   let !(cId, cs') = CS.insert @a cs in (mempty {filterWithout = Set.singleton cId}, cs')
 
 -- | Match all entities.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE all #-}
 all :: (Monad m) => i -> QueryReaderT m i a -> Entities -> (m [a], Entities)
 all i q es = let !(as, cs) = all' i q es in (as, es {E.components = cs})
 
 -- | Match all entities.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE all' #-}
 all' :: (Monad m) => i -> QueryReaderT m i a -> Entities -> (m [a], Components)
 all' i q es = let !(rs, cs', dynQ) = runQueryReader q (E.components es) in (allDyn rs i dynQ es, cs')
 
 -- | Match a single entity.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE single #-}
 single :: (HasCallStack) => i -> QueryReader i a -> Entities -> (a, Entities)
 single i q es = let !(a, cs) = single' i q es in (a, es {E.components = cs})
 
 -- | Match a single entity.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE single' #-}
 single' :: (HasCallStack) => i -> QueryReader i a -> Entities -> (a, Components)
 single' i q es = let !(rs, cs', dynQ) = runQueryReader q (E.components es) in (singleDyn rs i dynQ es, cs')
 
 -- | Match a single entity.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE singleMaybe #-}
 singleMaybe :: i -> QueryReader i a -> Entities -> (Maybe a, Entities)
 singleMaybe i q es = let !(a, cs) = singleMaybe' i q es in (a, es {E.components = cs})
 
 -- | Match a single entity.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE singleMaybe' #-}
 singleMaybe' :: i -> QueryReader i a -> Entities -> (Maybe a, Components)
 singleMaybe' i q es = let !(rs, cs', dynQ) = runQueryReader q (E.components es) in (singleMaybeDyn rs i dynQ es, cs')
diff --git a/src/Aztecs/ECS/Query/Reader/Class.hs b/src/Aztecs/ECS/Query/Reader/Class.hs
--- a/src/Aztecs/ECS/Query/Reader/Class.hs
+++ b/src/Aztecs/ECS/Query/Reader/Class.hs
@@ -13,15 +13,15 @@
 
 -- | Arrow for queries that can read from entities.
 --
--- @since 9.0
+-- @since 0.9
 class (Arrow arr) => ArrowQueryReader arr where
   -- | Fetch a `Component` by its type.
   --
-  -- @since 9.0
+  -- @since 0.9
   fetch :: (Component a) => arr () a
 
   -- | Fetch a `Component` by its type, returning `Nothing` if it doesn't exist.
   --
-  -- @since 9.0
+  -- @since 0.9
   fetchMaybe :: (Component a) => arr () (Maybe a)
   fetchMaybe = fetch >>> arr Just
diff --git a/src/Aztecs/ECS/System.hs b/src/Aztecs/ECS/System.hs
--- a/src/Aztecs/ECS/System.hs
+++ b/src/Aztecs/ECS/System.hs
@@ -47,21 +47,21 @@
 import Data.Set (Set)
 import Prelude hiding (all, filter, id, map, (.))
 
--- | @since 9.0
+-- | @since 0.9
 type System = SystemT STM
 
 -- | System to process queries in parallel.
 --
--- @since 9.0
+-- @since 0.9
 newtype SystemT m a = SystemT
   { -- | Run a system on a collection of `Entities`.
     --
-    -- @since 9.0
+    -- @since 0.9
     runSystemT :: ReaderT (TVar Entities) m a
   }
   deriving (Functor, Applicative, Monad, MonadFix)
 
--- | @since 9.0
+-- | @since 0.9
 instance MonadDynamicSystem (DynamicQueryT STM) System where
   mapDyn i cIds q = SystemT $ do
     wVar <- ask
@@ -87,7 +87,7 @@
     lift . modifyTVar wVar $ V.unview v'
     return o
 
--- | @since 9.0
+-- | @since 0.9
 instance MonadSystem (QueryT STM) System where
   map i q = SystemT $ do
     (rws, dynQ) <- runSystemT $ fromQuery q
@@ -107,7 +107,7 @@
             && F.all (\cId -> not (A.member cId $ nodeArchetype n)) (filterWithout dynF)
     runSystemT $ filterMapDyn i (Q.reads rws <> Q.writes rws) f' dynQ
 
--- | @since 9.0
+-- | @since 0.9
 instance MonadReaderSystem (QueryReaderT STM) System where
   all i q = SystemT $ do
     (cIds, dynQ) <- runSystemT $ fromQueryReader q
@@ -124,7 +124,7 @@
             && F.all (\cId -> not (A.member cId $ nodeArchetype n)) (filterWithout dynF)
     runSystemT $ filterDyn i cIds dynQ f'
 
--- | @since 9.0
+-- | @since 0.9
 instance MonadDynamicReaderSystem (DynamicQueryReaderT STM) System where
   allDyn i cIds q = SystemT $ do
     wVar <- ask
@@ -142,7 +142,7 @@
 
 -- | Convert a `QueryReaderT` to a `System`.
 --
--- @since 9.0
+-- @since 0.9
 fromQueryReader :: QueryReaderT STM i o -> System (Set ComponentID, DynamicQueryReaderT STM i o)
 fromQueryReader q = SystemT $ do
   wVar <- ask
@@ -153,7 +153,7 @@
 
 -- | Convert a `QueryT` to a `System`.
 --
--- @since 9.0
+-- @since 0.9
 fromQuery :: QueryT STM i o -> System (ReadsWrites, DynamicQueryT STM i o)
 fromQuery q = SystemT $ do
   wVar <- ask
diff --git a/src/Aztecs/ECS/System/Class.hs b/src/Aztecs/ECS/System/Class.hs
--- a/src/Aztecs/ECS/System/Class.hs
+++ b/src/Aztecs/ECS/System/Class.hs
@@ -16,21 +16,21 @@
 
 -- | Monadic system.
 --
--- @since 9.0
+-- @since 0.9
 class (Monad m) => MonadSystem q m | m -> q where
   -- | Map all matching entities with a query.
   --
-  -- @since 9.0
+  -- @since 0.9
   map :: i -> q i o -> m [o]
 
   -- | Map a single matching entity with a query, or @Nothing@.
   --
-  -- @since 9.0
+  -- @since 0.9
   mapSingleMaybe :: i -> q i o -> m (Maybe o)
 
   -- | Map a single matching entity with a query.
   --
-  -- @since 9.0
+  -- @since 0.9
   mapSingle :: (HasCallStack) => i -> q i o -> m o
   mapSingle i q = do
     res <- mapSingleMaybe i q
@@ -40,5 +40,5 @@
 
   -- | Map all matching entities with a query and filter.
   --
-  -- @since 9.0
+  -- @since 0.9
   filterMap :: i -> q i o -> QueryFilter -> m [o]
diff --git a/src/Aztecs/ECS/System/Dynamic/Class.hs b/src/Aztecs/ECS/System/Dynamic/Class.hs
--- a/src/Aztecs/ECS/System/Dynamic/Class.hs
+++ b/src/Aztecs/ECS/System/Dynamic/Class.hs
@@ -17,16 +17,16 @@
 
 -- | Monadic dynamic system.
 --
--- @since 9.0
+-- @since 0.9
 class (Monad m) => MonadDynamicSystem q m | m -> q where
   -- | Map all matching entities with a query.
   --
-  -- @since 9.0
+  -- @since 0.9
   mapDyn :: i -> Set ComponentID -> q i o -> m [o]
 
   -- | Map a single matching entity with a query, or @Nothing@.
   --
-  -- @since 9.0
+  -- @since 0.9
   mapSingleMaybeDyn :: i -> Set ComponentID -> q i a -> m (Maybe a)
 
   -- | Map a single matching entity with a query.
@@ -39,5 +39,5 @@
 
   -- | Map all matching entities with a query and filter.
   --
-  -- @since 9.0
+  -- @since 0.9
   filterMapDyn :: i -> Set ComponentID -> (Node -> Bool) -> q i a -> m [a]
diff --git a/src/Aztecs/ECS/System/Dynamic/Reader/Class.hs b/src/Aztecs/ECS/System/Dynamic/Reader/Class.hs
--- a/src/Aztecs/ECS/System/Dynamic/Reader/Class.hs
+++ b/src/Aztecs/ECS/System/Dynamic/Reader/Class.hs
@@ -17,16 +17,16 @@
 
 -- | Monadic dynamic reader system.
 --
--- @since 9.0
+-- @since 0.9
 class (Monad m) => MonadDynamicReaderSystem q m | m -> q where
   -- | Match all entities with a query.
   --
-  -- @since 9.0
+  -- @since 0.9
   allDyn :: i -> Set ComponentID -> q i o -> m [o]
 
   -- | Match a single entity with a query.
   --
-  -- @since 9.0
+  -- @since 0.9
   singleDyn :: (HasCallStack) => i -> Set ComponentID -> q i o -> m o
   singleDyn i cIds q = do
     os <- allDyn i cIds q
@@ -36,7 +36,7 @@
 
   -- | Match a single entity with a query, or Nothing.
   --
-  -- @since 9.0
+  -- @since 0.9
   singleMaybeDyn :: i -> Set ComponentID -> q i o -> m (Maybe o)
   singleMaybeDyn i cIds q = do
     os <- allDyn i cIds q
@@ -46,5 +46,5 @@
 
   -- | Match all entities with a query and filter.
   --
-  -- @since 9.0
+  -- @since 0.9
   filterDyn :: i -> Set ComponentID -> q i a -> (Node -> Bool) -> m [a]
diff --git a/src/Aztecs/ECS/System/Reader/Class.hs b/src/Aztecs/ECS/System/Reader/Class.hs
--- a/src/Aztecs/ECS/System/Reader/Class.hs
+++ b/src/Aztecs/ECS/System/Reader/Class.hs
@@ -16,16 +16,16 @@
 
 -- | Monadic reader system.
 --
--- @since 9.0
+-- @since 0.9
 class (Monad m) => MonadReaderSystem q m | m -> q where
   -- | Match all entities with a query.
   --
-  -- @since 9.0
+  -- @since 0.9
   all :: i -> q i o -> m [o]
 
   -- | Match a single entity with a query.
   --
-  -- @since 9.0
+  -- @since 0.9
   single :: (HasCallStack) => i -> q i o -> m o
   single i q = do
     os <- all i q
@@ -35,7 +35,7 @@
 
   -- | Match a single entity with a query, or @Nothing@.
   --
-  -- @since 9.0
+  -- @since 0.9
   singleMaybe :: i -> q i o -> m (Maybe o)
   singleMaybe i q = do
     os <- all i q
@@ -45,5 +45,5 @@
 
   -- | Match all entities with a query and filter.
   --
-  -- @since 9.0
+  -- @since 0.9
   filter :: i -> q i o -> QueryFilter -> m [o]
diff --git a/src/Aztecs/ECS/View.hs b/src/Aztecs/ECS/View.hs
--- a/src/Aztecs/ECS/View.hs
+++ b/src/Aztecs/ECS/View.hs
@@ -40,24 +40,24 @@
 
 -- | View into a `World`, containing a subset of archetypes.
 --
--- @since 9.0
+-- @since 0.9
 newtype View = View
   { -- | Archetypes contained in this view.
     --
-    -- @since 9.0
+    -- @since 0.9
     viewArchetypes :: Map ArchetypeID Node
   }
   deriving (Show, Semigroup, Monoid)
 
 -- | View into all archetypes containing the provided component IDs.
 --
--- @since 9.0
+-- @since 0.9
 view :: Set ComponentID -> Archetypes -> View
 view cIds as = View $ AS.find cIds as
 
 -- | View into a single archetype containing the provided component IDs.
 --
--- @since 9.0
+-- @since 0.9
 viewSingle :: Set ComponentID -> Archetypes -> Maybe View
 viewSingle cIds as = case Map.toList $ AS.find cIds as of
   [a] -> Just . View $ uncurry Map.singleton a
@@ -65,7 +65,7 @@
 
 -- | View into all archetypes containing the provided component IDs and matching the provided predicate.
 --
--- @since 9.0
+-- @since 0.9
 filterView ::
   Set ComponentID ->
   (Node -> Bool) ->
@@ -75,13 +75,13 @@
 
 -- | @True@ if the `View` is empty.
 --
--- @since 9.0
+-- @since 0.9
 null :: View -> Bool
 null = Map.null . viewArchetypes
 
 -- | "Un-view" a `View` back into a `World`.
 --
--- @since 9.0
+-- @since 0.9
 unview :: View -> Entities -> Entities
 unview v es =
   es
@@ -94,7 +94,7 @@
 
 -- | Query all matching entities in a `View`.
 --
--- @since 9.0
+-- @since 0.9
 allDyn :: (Monad m) => i -> DynamicQueryReaderT m i a -> View -> m [a]
 allDyn i q v =
   foldlM
@@ -107,7 +107,7 @@
 
 -- | Query all matching entities in a `View`.
 --
--- @since 9.0
+-- @since 0.9
 singleDyn :: (Monad m) => i -> DynamicQueryReaderT m i a -> View -> m (Maybe a)
 singleDyn i q v = do
   as <- allDyn i q v
@@ -117,7 +117,7 @@
 
 -- | Map all matching entities in a `View`.
 --
--- @since 9.0
+-- @since 0.9
 mapDyn :: (Monad m) => i -> DynamicQueryT m i a -> View -> m ([a], View)
 mapDyn i q v = do
   (as, arches) <-
@@ -132,7 +132,7 @@
 
 -- | Map a single matching entity in a `View`.
 --
--- @since 9.0
+-- @since 0.9
 mapSingleDyn :: (Monad m) => i -> DynamicQueryT m i a -> View -> m (Maybe a, View)
 mapSingleDyn i q v = do
   (as, arches) <- mapDyn i q v
diff --git a/src/Aztecs/ECS/World.hs b/src/Aztecs/ECS/World.hs
--- a/src/Aztecs/ECS/World.hs
+++ b/src/Aztecs/ECS/World.hs
@@ -39,22 +39,22 @@
 
 -- | World of entities and their components.
 --
--- @since 9.0
+-- @since 0.9
 data World = World
   { -- | Entities and their components.
     --
-    -- @since 9.0
+    -- @since 0.9
     entities :: !Entities,
     -- | Next unique entity identifier.
     --
-    -- @since 9.0
+    -- @since 0.9
     nextEntityId :: !EntityID
   }
   deriving (Show, Generic, NFData)
 
 -- | Empty `World`.
 --
--- @since 9.0
+-- @since 0.9
 empty :: World
 empty =
   World
@@ -64,7 +64,7 @@
 
 -- | Spawn a `Bundle` into the `World`.
 --
--- @since 9.0
+-- @since 0.9
 spawn :: Bundle -> World -> (EntityID, World)
 spawn b w =
   let e = nextEntityId w
@@ -72,31 +72,31 @@
 
 -- | Spawn an empty entity.
 --
--- @since 9.0
+-- @since 0.9
 spawnEmpty :: World -> (EntityID, World)
 spawnEmpty w = let e = nextEntityId w in (e, w {nextEntityId = EntityID $ unEntityId e + 1})
 
 -- | Insert a `Bundle` into an entity.
 --
--- @since 9.0
+-- @since 0.9
 insert :: EntityID -> Bundle -> World -> World
 insert e c w = w {entities = E.insert e c (entities w)}
 
 -- | Lookup a component in an entity.
 --
--- @since 9.0
+-- @since 0.9
 lookup :: forall a. (Component a) => EntityID -> World -> Maybe a
 lookup e w = E.lookup e $ entities w
 
 -- | Remove a component from an entity.
 --
--- @since 9.0
+-- @since 0.9
 remove :: forall a. (Component a) => EntityID -> World -> (Maybe a, World)
 remove e w = let (a, es) = E.remove e (entities w) in (a, w {entities = es})
 
 -- | Remove a component from an entity with its `ComponentID`.
 --
--- @since 9.0
+-- @since 0.9
 removeWithId :: forall a. (Component a) => EntityID -> ComponentID -> World -> (Maybe a, World)
 removeWithId e cId w = let (a, es) = E.removeWithId e cId (entities w) in (a, w {entities = es})
 
diff --git a/src/Aztecs/ECS/World/Archetype.hs b/src/Aztecs/ECS/World/Archetype.hs
--- a/src/Aztecs/ECS/World/Archetype.hs
+++ b/src/Aztecs/ECS/World/Archetype.hs
@@ -62,34 +62,34 @@
 -- | Archetype of entities and components.
 -- An archetype is guranteed to contain one of each stored component per entity.
 --
--- @since 9.0
+-- @since 0.9
 data Archetype = Archetype
   { -- | Component storages.
     --
-    -- @since 9.0
+    -- @since 0.9
     storages :: !(IntMap DynamicStorage),
     -- | Entities stored in this archetype.
     --
-    -- @since 9.0
+    -- @since 0.9
     entities :: !(Set EntityID)
   }
   deriving (Show, Generic, NFData)
 
 -- | Empty archetype.
 --
--- @since 9.0
+-- @since 0.9
 empty :: Archetype
 empty = Archetype {storages = IntMap.empty, entities = Set.empty}
 
 -- | Archetype with a single entity.
 --
--- @since 9.0
+-- @since 0.9
 singleton :: EntityID -> Archetype
 singleton e = Archetype {storages = IntMap.empty, entities = Set.singleton e}
 
 -- | Lookup a component `Storage` by its `ComponentID`.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE lookupStorage #-}
 lookupStorage :: (Component a) => ComponentID -> Archetype -> Maybe (StorageT a)
 lookupStorage cId w = do
@@ -98,14 +98,14 @@
 
 -- | Lookup a component by its `EntityID` and `ComponentID`.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE lookupComponent #-}
 lookupComponent :: (Component a) => EntityID -> ComponentID -> Archetype -> Maybe a
 lookupComponent e cId w = lookupComponents cId w Map.!? e
 
 -- | Lookup all components by their `ComponentID`.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE lookupComponents #-}
 lookupComponents :: (Component a) => ComponentID -> Archetype -> Map EntityID a
 lookupComponents cId arch = case lookupComponentsAscMaybe cId arch of
@@ -114,14 +114,14 @@
 
 -- | Lookup all components by their `ComponentID`, in ascending order by their `EntityID`.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE lookupComponentsAsc #-}
 lookupComponentsAsc :: (Component a) => ComponentID -> Archetype -> [a]
 lookupComponentsAsc cId = fromMaybe [] . lookupComponentsAscMaybe cId
 
 -- | Lookup all components by their `ComponentID`, in ascending order by their `EntityID`.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE lookupComponentsAscMaybe #-}
 lookupComponentsAscMaybe :: forall a. (Component a) => ComponentID -> Archetype -> Maybe [a]
 lookupComponentsAscMaybe cId arch = S.toAscList <$> lookupStorage @a cId arch
@@ -129,7 +129,7 @@
 -- | Insert a component into the archetype.
 -- This assumes the archetype contains one of each stored component per entity.
 --
--- @since 9.0
+-- @since 0.9
 insertComponent ::
   forall a. (Component a) => EntityID -> ComponentID -> a -> Archetype -> Archetype
 insertComponent e cId c arch =
@@ -139,13 +139,13 @@
 
 -- | @True@ if this archetype contains an entity with the provided `ComponentID`.
 --
--- @since 9.0
+-- @since 0.9
 member :: ComponentID -> Archetype -> Bool
 member cId = IntMap.member (unComponentId cId) . storages
 
 -- | Zip a list of components with a function and a component storage.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE zipWith #-}
 zipWith ::
   forall a c. (Component c) => [a] -> (a -> c -> c) -> ComponentID -> Archetype -> ([c], Archetype)
@@ -163,7 +163,7 @@
 
 -- | Zip a list of components with a monadic function and a component storage.
 --
--- @since 9.0
+-- @since 0.9
 zipWithM ::
   forall m a c. (Monad m, Component c) => [a] -> (a -> c -> m c) -> ComponentID -> Archetype -> m ([c], Archetype)
 zipWithM as f cId arch = do
@@ -180,7 +180,7 @@
 
 -- | Zip a list of components with a function and a component storage.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE zipWith_ #-}
 zipWith_ ::
   forall a c. (Component c) => [a] -> (a -> c -> c) -> ComponentID -> Archetype -> Archetype
@@ -196,7 +196,7 @@
 
 -- | Insert a list of components into the archetype, sorted in ascending order by their `EntityID`.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE insertAscList #-}
 insertAscList :: forall a. (Component a) => ComponentID -> [a] -> Archetype -> Archetype
 insertAscList cId as arch =
@@ -205,7 +205,7 @@
 
 -- | Remove an entity from an archetype, returning its components.
 --
--- @since 9.0
+-- @since 0.9
 remove :: EntityID -> Archetype -> (IntMap Dynamic, Archetype)
 remove e arch =
   let go (dynAcc, archAcc) (cId, dynS) =
@@ -221,7 +221,7 @@
 
 -- | Remove an entity from an archetype, returning its component storages.
 --
--- @since 9.0
+-- @since 0.9
 removeStorages :: EntityID -> Archetype -> (IntMap DynamicStorage, Archetype)
 removeStorages e arch =
   let go (dynAcc, archAcc) (cId, dynS) =
@@ -237,7 +237,7 @@
 
 -- | Insert a map of component storages and their `EntityID` into the archetype.
 --
--- @since 9.0
+-- @since 0.9
 insertComponents :: EntityID -> IntMap Dynamic -> Archetype -> Archetype
 insertComponents e cs arch =
   let f archAcc (itemCId, dyn) =
diff --git a/src/Aztecs/ECS/World/Archetypes.hs b/src/Aztecs/ECS/World/Archetypes.hs
--- a/src/Aztecs/ECS/World/Archetypes.hs
+++ b/src/Aztecs/ECS/World/Archetypes.hs
@@ -56,26 +56,26 @@
 
 -- | `Archetype` ID.
 --
--- @since 9.0
+-- @since 0.9
 newtype ArchetypeID = ArchetypeID
   { -- | Unique integer identifier.
     --
-    -- @since 9.0
+    -- @since 0.9
     unArchetypeId :: Int
   }
   deriving newtype (Eq, Ord, Show, NFData)
 
 -- | Node in `Archetypes`.
 --
--- @since 9.0
+-- @since 0.9
 data Node = Node
   { -- | Unique set of `ComponentID`s of this `Node`.
     --
-    -- @since 9.0
+    -- @since 0.9
     nodeComponentIds :: !(Set ComponentID),
     -- | `Archetype` of this `Node`.
     --
-    -- @since 9.0
+    -- @since 0.9
     nodeArchetype :: !Archetype
   }
   deriving (Show, Generic, NFData)
@@ -84,26 +84,26 @@
 data Archetypes = Archetypes
   { -- | Archetype nodes in the map.
     --
-    -- @since 9.0
+    -- @since 0.9
     nodes :: !(Map ArchetypeID Node),
     -- | Mapping of unique `ComponentID` sets to `ArchetypeID`s.
     --
-    -- @since 9.0
+    -- @since 0.9
     archetypeIds :: !(Map (Set ComponentID) ArchetypeID),
     -- | Next unique `ArchetypeID`.
     --
-    -- @since 9.0
+    -- @since 0.9
     nextArchetypeId :: !ArchetypeID,
     -- | Mapping of `ComponentID`s to `ArchetypeID`s of `Archetypes` that contain them.
     --
-    -- @since 9.0
+    -- @since 0.9
     componentIds :: !(Map ComponentID (Set ArchetypeID))
   }
   deriving (Show, Generic, NFData)
 
 -- | Empty `Archetypes`.
 --
--- @since 9.0
+-- @since 0.9
 empty :: Archetypes
 empty =
   Archetypes
@@ -115,7 +115,7 @@
 
 -- | Insert an archetype by its set of `ComponentID`s.
 --
--- @since 9.0
+-- @since 0.9
 insertArchetype :: Set ComponentID -> Node -> Archetypes -> (ArchetypeID, Archetypes)
 insertArchetype cIds n arches =
   let aId = nextArchetypeId arches
@@ -130,14 +130,14 @@
 
 -- | Adjust an `Archetype` by its `ArchetypeID`.
 --
--- @since 9.0
+-- @since 0.9
 adjustArchetype :: ArchetypeID -> (Archetype -> Archetype) -> Archetypes -> Archetypes
 adjustArchetype aId f arches =
   arches {nodes = Map.adjust (\node -> node {nodeArchetype = f (nodeArchetype node)}) aId (nodes arches)}
 
 -- | Find `ArchetypeID`s containing a set of `ComponentID`s.
 --
--- @since 9.0
+-- @since 0.9
 findArchetypeIds :: Set ComponentID -> Archetypes -> Set ArchetypeID
 findArchetypeIds cIds arches = case mapMaybe (\cId -> Map.lookup cId (componentIds arches)) (Set.elems cIds) of
   (aId : aIds') -> foldl' Set.intersection aId aIds'
@@ -145,13 +145,13 @@
 
 -- | Lookup `Archetype`s containing a set of `ComponentID`s.
 --
--- @since 9.0
+-- @since 0.9
 find :: Set ComponentID -> Archetypes -> Map ArchetypeID Node
 find cIds arches = Map.fromSet (\aId -> nodes arches Map.! aId) (findArchetypeIds cIds arches)
 
 -- | Map over `Archetype`s containing a set of `ComponentID`s.
 --
--- @since 9.0
+-- @since 0.9
 map :: Set ComponentID -> (Archetype -> (a, Archetype)) -> Archetypes -> ([a], Archetypes)
 map cIds f arches =
   let go (acc, archAcc) aId =
@@ -163,19 +163,19 @@
 
 -- | Lookup an `ArchetypeID` by its set of `ComponentID`s.
 --
--- @since 9.0
+-- @since 0.9
 lookupArchetypeId :: Set ComponentID -> Archetypes -> Maybe ArchetypeID
 lookupArchetypeId cIds arches = Map.lookup cIds (archetypeIds arches)
 
 -- | Lookup an `Archetype` by its `ArchetypeID`.
 --
--- @since 9.0
+-- @since 0.9
 lookup :: ArchetypeID -> Archetypes -> Maybe Node
 lookup aId arches = Map.lookup aId (nodes arches)
 
 -- | Insert a component into an entity with its `ComponentID`.
 --
--- @since 9.0
+-- @since 0.9
 insert ::
   EntityID ->
   ArchetypeID ->
@@ -185,34 +185,35 @@
   (Maybe ArchetypeID, Archetypes)
 insert e aId cIds b arches = case lookup aId arches of
   Just node ->
-    if cIds == nodeComponentIds node
+    if Set.isSubsetOf cIds $ nodeComponentIds node
       then
         let go n = n {nodeArchetype = runDynamicBundle b e $ nodeArchetype n}
          in (Nothing, arches {nodes = Map.adjust go aId $ nodes arches})
-      else case lookupArchetypeId cIds arches of
-        Just nextAId ->
-          let !(cs, arch') = A.remove e $ nodeArchetype node
-              node' = node {nodeArchetype = arch'}
-              !arches' = arches {nodes = Map.insert aId node' (nodes arches)}
-              adjustNode nextNode =
-                let !nextArch = A.insertComponents e cs $ nodeArchetype nextNode
-                 in nextNode {nodeArchetype = runDynamicBundle b e nextArch}
-           in (Just nextAId, arches' {nodes = Map.adjust adjustNode nextAId (nodes arches')})
-        Nothing ->
-          let !(s, arch') = A.removeStorages e $ nodeArchetype node
-              !n =
-                Node
-                  { nodeComponentIds = cIds,
-                    nodeArchetype = runDynamicBundle b e (Archetype {storages = s, entities = Set.singleton e})
-                  }
-              !(nextAId, arches') = insertArchetype cIds n arches
-           in let nodes' = Map.insert aId (node {nodeArchetype = arch'}) (nodes arches')
-               in (Just nextAId, arches' {nodes = nodes'})
+      else
+        let cIds' = cIds <> nodeComponentIds node
+         in case lookupArchetypeId cIds' arches of
+              Just nextAId ->
+                let !(cs, arch) = A.remove e $ nodeArchetype node
+                    node' = node {nodeArchetype = arch}
+                    !nodes' = Map.insert aId node' $ nodes arches
+                    adjustNode nextNode =
+                      let nextArch = nodeArchetype nextNode
+                          nextArch' = nextArch {A.entities = Set.insert e $ A.entities nextArch}
+                          !nextArch'' = A.insertComponents e cs nextArch'
+                       in nextNode {nodeArchetype = runDynamicBundle b e nextArch''}
+                 in (Just nextAId, arches {nodes = Map.adjust adjustNode nextAId nodes'})
+              Nothing ->
+                let !(s, arch) = A.removeStorages e $ nodeArchetype node
+                    nodes' = Map.insert aId node {nodeArchetype = arch} $ nodes arches
+                    !nextArch = runDynamicBundle b e Archetype {storages = s, entities = Set.singleton e}
+                    !n = Node {nodeComponentIds = cIds', nodeArchetype = nextArch}
+                    !(nextAId, arches') = insertArchetype cIds' n arches {nodes = nodes'}
+                 in (Just nextAId, arches')
   Nothing -> (Nothing, arches)
 
 -- | Remove a component from an entity with its `ComponentID`.
 --
--- @since 9.0
+-- @since 0.9
 remove ::
   (Component a) =>
   EntityID ->
diff --git a/src/Aztecs/ECS/World/Bundle.hs b/src/Aztecs/ECS/World/Bundle.hs
--- a/src/Aztecs/ECS/World/Bundle.hs
+++ b/src/Aztecs/ECS/World/Bundle.hs
@@ -35,38 +35,38 @@
 
 -- | Bundle of components.
 --
--- @since 9.0
+-- @since 0.9
 newtype Bundle = Bundle
   { -- | Unwrap the bundle.
     --
-    -- @since 9.0
+    -- @since 0.9
     unBundle :: Components -> (Set ComponentID, Components, DynamicBundle)
   }
 
--- | @since 9.0
+-- | @since 0.9
 instance Monoid Bundle where
   mempty = Bundle (Set.empty,,mempty)
 
--- | @since 9.0
+-- | @since 0.9
 instance Semigroup Bundle where
   Bundle b1 <> Bundle b2 = Bundle $ \cs ->
     let (cIds1, cs', d1) = b1 cs
         (cIds2, cs'', d2) = b2 cs'
      in (cIds1 <> cIds2, cs'', d1 <> d2)
 
--- | @since 9.0
+-- | @since 0.9
 instance MonoidBundle Bundle where
   bundle :: forall a. (Component a) => a -> Bundle
   bundle a = Bundle $ \cs ->
     let (cId, cs') = CS.insert @a cs in (Set.singleton cId, cs', dynBundle cId a)
 
--- | @since 9.0
+-- | @since 0.9
 instance MonoidDynamicBundle Bundle where
   dynBundle cId c = Bundle (Set.singleton cId,,dynBundle cId c)
 
 -- | Insert a bundle of components into an archetype.
 --
--- @since 9.0
+-- @since 0.9
 runBundle :: Bundle -> Components -> EntityID -> Archetype -> (Components, Archetype)
 runBundle b cs eId arch =
   let !(_, cs', d) = unBundle b cs
diff --git a/src/Aztecs/ECS/World/Bundle/Class.hs b/src/Aztecs/ECS/World/Bundle/Class.hs
--- a/src/Aztecs/ECS/World/Bundle/Class.hs
+++ b/src/Aztecs/ECS/World/Bundle/Class.hs
@@ -15,9 +15,9 @@
 
 -- | Monoid bundle of components.
 --
--- @since 9.0
+-- @since 0.9
 class (Monoid a) => MonoidBundle a where
   -- | Add a component to the bundle.
   --
-  -- @since 9.0
+  -- @since 0.9
   bundle :: forall c. (Component c) => c -> a
diff --git a/src/Aztecs/ECS/World/Bundle/Dynamic.hs b/src/Aztecs/ECS/World/Bundle/Dynamic.hs
--- a/src/Aztecs/ECS/World/Bundle/Dynamic.hs
+++ b/src/Aztecs/ECS/World/Bundle/Dynamic.hs
@@ -14,17 +14,17 @@
 
 -- | Dynamic bundle of components.
 --
--- @since 9.0
+-- @since 0.9
 newtype DynamicBundle = DynamicBundle {runDynamicBundle :: EntityID -> Archetype -> Archetype}
 
--- | @since 9.0
+-- | @since 0.9
 instance Semigroup DynamicBundle where
   DynamicBundle d1 <> DynamicBundle d2 = DynamicBundle $ \eId arch -> d2 eId (d1 eId arch)
 
--- | @since 9.0
+-- | @since 0.9
 instance Monoid DynamicBundle where
   mempty = DynamicBundle $ \_ arch -> arch
 
--- | @since 9.0
+-- | @since 0.9
 instance MonoidDynamicBundle DynamicBundle where
   dynBundle cId a = DynamicBundle $ \eId arch -> insertComponent eId cId a arch
diff --git a/src/Aztecs/ECS/World/Bundle/Dynamic/Class.hs b/src/Aztecs/ECS/World/Bundle/Dynamic/Class.hs
--- a/src/Aztecs/ECS/World/Bundle/Dynamic/Class.hs
+++ b/src/Aztecs/ECS/World/Bundle/Dynamic/Class.hs
@@ -12,9 +12,9 @@
 
 -- | Monoid bundle of dynamic components.
 --
--- @since 9.0
+-- @since 0.9
 class MonoidDynamicBundle a where
   -- | Add a component to the bundle by its `ComponentID`.
   --
-  -- @since 9.0
+  -- @since 0.9
   dynBundle :: (Component c) => ComponentID -> c -> a
diff --git a/src/Aztecs/ECS/World/Components.hs b/src/Aztecs/ECS/World/Components.hs
--- a/src/Aztecs/ECS/World/Components.hs
+++ b/src/Aztecs/ECS/World/Components.hs
@@ -33,22 +33,22 @@
 
 -- | Component ID map.
 --
--- @since 9.0
+-- @since 0.9
 data Components = Components
   { -- | Map of component types to identifiers.
     --
-    -- @since 9.0
+    -- @since 0.9
     componentIds :: !(Map TypeRep ComponentID),
     -- | Next unique component identifier.
     --
-    -- @since 9.0
+    -- @since 0.9
     nextComponentId :: !ComponentID
   }
   deriving (Show, Generic, NFData)
 
 -- | Empty `Components`.
 --
--- @since 9.0
+-- @since 0.9
 empty :: Components
 empty =
   Components
@@ -58,13 +58,13 @@
 
 -- | Lookup a component ID by type.
 --
--- @since 9.0
+-- @since 0.9
 lookup :: forall a. (Typeable a) => Components -> Maybe ComponentID
 lookup cs = Map.lookup (typeOf (Proxy @a)) (componentIds cs)
 
 -- | Insert a component ID by type, if it does not already exist.
 --
--- @since 9.0
+-- @since 0.9
 insert :: forall a. (Component a) => Components -> (ComponentID, Components)
 insert cs = case lookup @a cs of
   Just cId -> (cId, cs)
@@ -72,7 +72,7 @@
 
 -- | Insert a component ID by type.
 --
--- @since 9.0
+-- @since 0.9
 insert' :: forall c. (Component c) => Components -> (ComponentID, Components)
 insert' cs =
   let !cId = nextComponentId cs
diff --git a/src/Aztecs/ECS/World/Entities.hs b/src/Aztecs/ECS/World/Entities.hs
--- a/src/Aztecs/ECS/World/Entities.hs
+++ b/src/Aztecs/ECS/World/Entities.hs
@@ -50,26 +50,26 @@
 
 -- | World of entities and their components.
 --
--- @since 9.0
+-- @since 0.9
 data Entities = Entities
   { -- | Archetypes.
     --
-    -- @since 9.0
+    -- @since 0.9
     archetypes :: !Archetypes,
     -- | Components.
     --
-    -- @since 9.0
+    -- @since 0.9
     components :: !Components,
     -- | Entities and their archetype identifiers.
     --
-    -- @since 9.0
+    -- @since 0.9
     entities :: !(Map EntityID ArchetypeID)
   }
   deriving (Show, Generic, NFData)
 
 -- | Empty `World`.
 --
--- @since 9.0
+-- @since 0.9
 empty :: Entities
 empty =
   Entities
@@ -80,7 +80,7 @@
 
 -- | Spawn a `Bundle`.
 --
--- @since 9.0
+-- @since 0.9
 spawn :: EntityID -> Bundle -> Entities -> Entities
 spawn eId b w =
   let (cIds, components', dynB) = unBundle b (components w)
@@ -113,7 +113,7 @@
 
 -- | Spawn a `DynamicBundle` with a specified `ArchetypeID`.
 --
--- @since 9.0
+-- @since 0.9
 spawnWithArchetypeId ::
   EntityID ->
   ArchetypeID ->
@@ -129,7 +129,7 @@
 
 -- | Insert a component into an entity.
 --
--- @since 9.0
+-- @since 0.9
 insert :: EntityID -> Bundle -> Entities -> Entities
 insert e b w =
   let !(cIds, components', dynB) = unBundle b (components w)
@@ -137,32 +137,26 @@
 
 -- | Insert a component into an entity with its `ComponentID`.
 --
--- @since 9.0
+-- @since 0.9
 insertDyn :: EntityID -> Set ComponentID -> DynamicBundle -> Entities -> Entities
-insertDyn e cIds b w = case Map.lookup e (entities w) of
+insertDyn e cIds b w = case Map.lookup e $ entities w of
   Just aId ->
     let (maybeNextAId, arches) = AS.insert e aId cIds b $ archetypes w
         es = case maybeNextAId of
-          Just nextAId -> Map.insert e nextAId (entities w)
+          Just nextAId -> Map.insert e nextAId $ entities w
           Nothing -> entities w
      in w {archetypes = arches, entities = es}
-  Nothing -> case AS.lookupArchetypeId cIds (archetypes w) of
+  Nothing -> case AS.lookupArchetypeId cIds $ archetypes w of
     Just aId -> spawnWithArchetypeId e aId b w
     Nothing ->
-      let (aId, arches) =
-            AS.insertArchetype
-              cIds
-              ( Node
-                  { nodeComponentIds = cIds,
-                    nodeArchetype = runDynamicBundle b e $ A.singleton e
-                  }
-              )
-              (archetypes w)
+      let arch = runDynamicBundle b e $ A.singleton e
+          node = Node {nodeComponentIds = cIds, nodeArchetype = arch}
+          (aId, arches) = AS.insertArchetype cIds node $ archetypes w
        in w {archetypes = arches, entities = Map.insert e aId (entities w)}
 
 -- | Lookup a component in an entity.
 --
--- @since 9.0
+-- @since 0.9
 lookup :: forall a. (Component a) => EntityID -> Entities -> Maybe a
 lookup e w = do
   !cId <- CS.lookup @a $ components w
@@ -172,7 +166,7 @@
 
 -- | Insert a component into an entity.
 --
--- @since 9.0
+-- @since 0.9
 remove :: forall a. (Component a) => EntityID -> Entities -> (Maybe a, Entities)
 remove e w =
   let !(cId, components') = CS.insert @a (components w)
@@ -180,7 +174,7 @@
 
 -- | Remove a component from an entity with its `ComponentID`.
 --
--- @since 9.0
+-- @since 0.9
 removeWithId :: forall a. (Component a) => EntityID -> ComponentID -> Entities -> (Maybe a, Entities)
 removeWithId e cId w = case Map.lookup e (entities w) of
   Just aId ->
@@ -193,7 +187,7 @@
 
 -- | Despawn an entity, returning its components.
 --
--- @since 9.0
+-- @since 0.9
 despawn :: EntityID -> Entities -> (IntMap Dynamic, Entities)
 despawn e w =
   let res = do
diff --git a/src/Aztecs/ECS/World/Storage.hs b/src/Aztecs/ECS/World/Storage.hs
--- a/src/Aztecs/ECS/World/Storage.hs
+++ b/src/Aztecs/ECS/World/Storage.hs
@@ -19,46 +19,46 @@
 
 -- | Component storage, containing zero or many components of the same type.
 --
--- @since 9.0
+-- @since 0.9
 class (Typeable s, NFData s, Typeable a) => Storage a s where
   -- | Storage with a single component.
   --
-  -- @since 9.0
+  -- @since 0.9
   singleton :: a -> s
 
   -- | List of all components in the storage in ascending order.
   --
-  -- @since 9.0
+  -- @since 0.9
   toAscList :: s -> [a]
 
   -- | Convert a sorted list of components (in ascending order) into a storage.
   --
-  -- @since 9.0
+  -- @since 0.9
   fromAscList :: [a] -> s
 
   -- | Map a function over all components in the storage.
   --
   --
-  -- @since 9.0
+  -- @since 0.9
   map :: (a -> a) -> s -> s
 
   -- | Map a function with some input over all components in the storage.
   --
-  -- @since 9.0
+  -- @since 0.9
   zipWith :: (i -> a -> a) -> [i] -> s -> ([a], s)
 
   -- | Map a monadic function with some input over all components in the storage.
   --
-  -- @since 9.0
+  -- @since 0.9
   zipWithM :: (Monad m) => (i -> a -> m a) -> [i] -> s -> m ([a], s)
 
   -- | Map a function with some input over all components in the storage.
   --
-  -- @since 9.0
+  -- @since 0.9
   zipWith_ :: (i -> a -> a) -> [i] -> s -> s
   zipWith_ f is as = snd $ zipWith f is as
 
--- | @since 9.0
+-- | @since 0.9
 instance (Typeable a, NFData a) => Storage a [a] where
   {-# INLINE singleton #-}
   singleton a = [a]
diff --git a/src/Aztecs/ECS/World/Storage/Dynamic.hs b/src/Aztecs/ECS/World/Storage/Dynamic.hs
--- a/src/Aztecs/ECS/World/Storage/Dynamic.hs
+++ b/src/Aztecs/ECS/World/Storage/Dynamic.hs
@@ -32,41 +32,41 @@
 
 -- | Dynamic storage of components.
 --
--- @since 9.0
+-- @since 0.9
 data DynamicStorage = DynamicStorage
   { -- | Dynamic storage.
     --
-    -- @since 9.0
+    -- @since 0.9
     storageDyn :: !Dynamic,
     -- | Singleton storage.
     --
-    -- @since 9.0
+    -- @since 0.9
     singletonDyn' :: !(Dynamic -> Dynamic),
     -- | Convert this storage to an ascending list.
     --
-    -- @since 9.0
+    -- @since 0.9
     toAscListDyn' :: !(Dynamic -> [Dynamic]),
     -- | Convert from an ascending list.
     --
-    -- @since 9.0
+    -- @since 0.9
     fromAscListDyn' :: !([Dynamic] -> Dynamic),
     -- | Reduce this storage to normal form.
     --
-    -- @since 9.0
+    -- @since 0.9
     storageRnf :: !(Dynamic -> ())
   }
 
--- | @since 9.0
+-- | @since 0.9
 instance Show DynamicStorage where
   show s = "DynamicStorage " ++ show (storageDyn s)
 
--- | @since 9.0
+-- | @since 0.9
 instance NFData DynamicStorage where
   rnf s = storageRnf s (storageDyn s)
 
 -- | Create a dynamic storage from a storage.
 --
--- @since 9.0
+-- @since 0.9
 {-# INLINE dynStorage #-}
 dynStorage :: forall a s. (S.Storage a s) => s -> DynamicStorage
 dynStorage s =
@@ -80,18 +80,18 @@
 
 -- | Singleton dynamic storage.
 --
--- @since 9.0
+-- @since 0.9
 singletonDyn :: Dynamic -> DynamicStorage -> DynamicStorage
 singletonDyn dyn s = s {storageDyn = singletonDyn' s dyn}
 
 -- | Convert from an ascending list.
 --
--- @since 9.0
+-- @since 0.9
 fromAscListDyn :: [Dynamic] -> DynamicStorage -> DynamicStorage
 fromAscListDyn dyns s = s {storageDyn = fromAscListDyn' s dyns}
 
 -- | Convert this storage to an ascending list.
 --
--- @since 9.0
+-- @since 0.9
 toAscListDyn :: DynamicStorage -> [Dynamic]
 toAscListDyn = toAscListDyn' <*> storageDyn
diff --git a/src/Aztecs/Hierarchy.hs b/src/Aztecs/Hierarchy.hs
--- a/src/Aztecs/Hierarchy.hs
+++ b/src/Aztecs/Hierarchy.hs
@@ -48,46 +48,46 @@
 
 -- | Parent component.
 --
--- @since 9.0
+-- @since 0.9
 newtype Parent = Parent
   { -- | Parent entity ID.
     --
-    -- @since 9.0
+    -- @since 0.9
     unParent :: EntityID
   }
   deriving (Eq, Ord, Show, Generic, NFData)
 
--- | @since 9.0
+-- | @since 0.9
 instance Component Parent
 
 -- | Parent internal state component.
 --
--- @since 9.0
+-- @since 0.9
 newtype ParentState = ParentState {unParentState :: EntityID}
   deriving (Show, Generic, NFData)
 
--- | @since 9.0
+-- | @since 0.9
 instance Component ParentState
 
 -- | Children component.
 --
--- @since 9.0
+-- @since 0.9
 newtype Children = Children {unChildren :: Set EntityID}
   deriving (Eq, Ord, Show, Semigroup, Monoid, Generic, NFData)
 
--- | @since 9.0
+-- | @since 0.9
 instance Component Children
 
 -- | Child internal state component.
 newtype ChildState = ChildState {unChildState :: Set EntityID}
   deriving (Show, Generic, NFData)
 
--- | @since 9.0
+-- | @since 0.9
 instance Component ChildState
 
 -- | Update the parent-child relationships.
 --
--- @since 9.0
+-- @since 0.9
 update ::
   ( ArrowQueryReader qr,
     ArrowDynamicQueryReader qr,
@@ -158,59 +158,59 @@
 
 -- | Hierarchy of entities.
 --
--- @since 9.0
+-- @since 0.9
 data Hierarchy a = Node
   { -- | Entity ID.
     --
-    -- @since 9.0
+    -- @since 0.9
     nodeEntityId :: EntityID,
     -- | Entity components.
     nodeEntity :: a,
     -- | Child nodes.
     --
-    -- @since 9.0
+    -- @since 0.9
     nodeChildren :: [Hierarchy a]
   }
   deriving (Functor)
 
--- | @since 9.0
+-- | @since 0.9
 instance Foldable Hierarchy where
   foldMap f n = f (nodeEntity n) <> foldMap (foldMap f) (nodeChildren n)
 
--- | @since 9.0
+-- | @since 0.9
 instance Traversable Hierarchy where
   traverse f n =
     Node (nodeEntityId n) <$> f (nodeEntity n) <*> traverse (traverse f) (nodeChildren n)
 
 -- | Convert a hierarchy to a list of entity IDs and components.
 --
--- @since 9.0
+-- @since 0.9
 toList :: Hierarchy a -> [(EntityID, a)]
 toList n = (nodeEntityId n, nodeEntity n) : concatMap toList (nodeChildren n)
 
 -- | Fold a hierarchy with a function that takes the entity ID, entity, and accumulator.
 --
--- @since 9.0
+-- @since 0.9
 foldWithKey :: (EntityID -> a -> b -> b) -> Hierarchy a -> b -> b
 foldWithKey f n b = f (nodeEntityId n) (nodeEntity n) (foldr (foldWithKey f) b (nodeChildren n))
 
 -- | Map a hierarchy with a function that takes the entity ID and entity.
 --
--- @since 9.0
+-- @since 0.9
 mapWithKey :: (EntityID -> a -> b) -> Hierarchy a -> Hierarchy b
 mapWithKey f n =
   Node (nodeEntityId n) (f (nodeEntityId n) (nodeEntity n)) (map (mapWithKey f) (nodeChildren n))
 
 -- | Map a hierarchy with a function that takes the entity ID, entity, and accumulator.
 --
--- @since 9.0
+-- @since 0.9
 mapWithAccum :: (EntityID -> a -> b -> (c, b)) -> b -> Hierarchy a -> Hierarchy c
 mapWithAccum f b n = case f (nodeEntityId n) (nodeEntity n) b of
   (c, b') -> Node (nodeEntityId n) c (map (mapWithAccum f b') (nodeChildren n))
 
 -- | System to read a hierarchy of parents to children with the given query.
 --
--- @since 9.0
+-- @since 0.9
 hierarchy ::
   (ArrowQueryReader q, ArrowDynamicQueryReader q, MonadReaderSystem q s) =>
   EntityID ->
@@ -232,7 +232,7 @@
 
 -- | Build all hierarchies of parents to children, joined with the given query.
 --
--- @since 9.0
+-- @since 0.9
 hierarchies ::
   (ArrowQueryReader q, ArrowDynamicQueryReader q, MonadReaderSystem q s) =>
   i ->
@@ -255,7 +255,7 @@
 
 -- | Build a hierarchy of parents to children.
 --
--- @since 9.0
+-- @since 0.9
 hierarchy' :: EntityID -> Map EntityID (Set EntityID, a) -> Maybe (Hierarchy a)
 hierarchy' e childMap = case Map.lookup e childMap of
   Just (cs, a) ->
diff --git a/src/Aztecs/Input.hs b/src/Aztecs/Input.hs
--- a/src/Aztecs/Input.hs
+++ b/src/Aztecs/Input.hs
@@ -37,7 +37,7 @@
 
 -- | Keyboard key.
 --
--- @since 9.0
+-- @since 0.9
 data Key
   = KeyA
   | KeyB
@@ -138,49 +138,49 @@
 
 -- | Keyboard input component.
 --
--- @since 9.0
+-- @since 0.9
 data KeyboardInput = KeyboardInput
   { -- | Keyboard events that occured this frame.
     --
-    -- @since 9.0
+    -- @since 0.9
     keyboardEvents :: !(Map Key InputMotion),
     -- | Keys that are currently pressed.
     --
-    -- @since 9.0
+    -- @since 0.9
     keyboardPressed :: !(Set Key)
   }
   deriving (Show, Generic, NFData)
 
--- | @since 9.0
+-- | @since 0.9
 instance Component KeyboardInput
 
 -- | Empty keyboard input.
 --
--- @since 9.0
+-- @since 0.9
 keyboardInput :: KeyboardInput
 keyboardInput = KeyboardInput Map.empty Set.empty
 
 -- | Input motion kind.
 --
--- @since 9.0
+-- @since 0.9
 data InputMotion = Pressed | Released
   deriving (Show, Eq, Generic, NFData)
 
 -- | @True@ if this key is currently pressed.
 --
--- @since 9.0
+-- @since 0.9
 isKeyPressed :: Key -> KeyboardInput -> Bool
 isKeyPressed key kb = Set.member key $ keyboardPressed kb
 
 -- | Check for a key event that occured this frame.
 --
--- @since 9.0
+-- @since 0.9
 keyEvent :: Key -> KeyboardInput -> Maybe InputMotion
 keyEvent key kb = Map.lookup key $ keyboardEvents kb
 
 -- | @True@ if this key was pressed this frame.
 --
--- @since 9.0
+-- @since 0.9
 wasKeyPressed :: Key -> KeyboardInput -> Bool
 wasKeyPressed key kb = case keyEvent key kb of
   Just Pressed -> True
@@ -188,7 +188,7 @@
 
 -- | @True@ if this key was released this frame.
 --
--- @since 9.0
+-- @since 0.9
 wasKeyReleased :: Key -> KeyboardInput -> Bool
 wasKeyReleased key kb = case keyEvent key kb of
   Just Released -> True
@@ -196,7 +196,7 @@
 
 -- | Handle a keyboard event.
 --
--- @since 9.0
+-- @since 0.9
 handleKeyboardEvent :: Key -> InputMotion -> KeyboardInput -> KeyboardInput
 handleKeyboardEvent key motion kb =
   KeyboardInput
@@ -208,7 +208,7 @@
 
 -- | Mouse button kind.
 --
--- @since 9.0
+-- @since 0.9
 data MouseButton
   = ButtonLeft
   | ButtonMiddle
@@ -221,35 +221,35 @@
 
 -- | Mouse input component.
 --
--- @since 9.0
+-- @since 0.9
 data MouseInput = MouseInput
   { -- | Mouse position in screen-space.
     --
-    -- @since 9.0
+    -- @since 0.9
     mousePosition :: !(Point V2 Int),
     -- | Mouse offset since last frame.
     --
-    -- @since 9.0
+    -- @since 0.9
     mouseOffset :: !(V2 Int),
     -- | Mouse button states.
     --
-    -- @since 9.0
+    -- @since 0.9
     mouseButtons :: !(Map MouseButton InputMotion)
   }
   deriving (Show, Generic, NFData)
 
--- | @since 9.0
+-- | @since 0.9
 instance Component MouseInput
 
 -- | Empty mouse input.
 --
--- @since 9.0
+-- @since 0.9
 mouseInput :: MouseInput
 mouseInput = MouseInput (P 0) (V2 0 0) Map.empty
 
 -- | Handle a mouse motion event.
 --
--- @since 9.0
+-- @since 0.9
 handleMouseMotion :: V2 Int -> MouseInput -> MouseInput
 handleMouseMotion delta mouse =
   mouse
diff --git a/src/Aztecs/Time.hs b/src/Aztecs/Time.hs
--- a/src/Aztecs/Time.hs
+++ b/src/Aztecs/Time.hs
@@ -18,11 +18,11 @@
 
 -- | Time component.
 --
--- @since 9.0
+-- @since 0.9
 newtype Time = Time
   { -- | Elapsed time (in milliseconds).
     --
-    -- @since 9.0
+    -- @since 0.9
     elapsedMS :: Word32
   }
   deriving (Eq, Ord, Num, Show, Generic, NFData)
diff --git a/src/Aztecs/Transform.hs b/src/Aztecs/Transform.hs
--- a/src/Aztecs/Transform.hs
+++ b/src/Aztecs/Transform.hs
@@ -48,72 +48,72 @@
 
 -- | Transform component.
 --
--- @since 9.0
+-- @since 0.9
 data Transform v r = Transform
   { -- | Translation.
     --
-    -- @since 9.0
+    -- @since 0.9
     transformTranslation :: !v,
     -- | Rotation.
     --
-    -- @since 9.0
+    -- @since 0.9
     transformRotation :: !r,
     -- | Scale.
     --
-    -- @since 9.0
+    -- @since 0.9
     transformScale :: !v
   }
   deriving (Eq, Show, Generic, NFData)
 
--- | @since 9.0
+-- | @since 0.9
 instance (Num v, Num r) => Semigroup (Transform v r) where
   Transform t1 r1 s1 <> Transform t2 r2 s2 = Transform (t1 + t2) (r1 + r2) (s1 + s2)
 
--- | @since 9.0
+-- | @since 0.9
 instance (Num v, Num r) => Monoid (Transform v r) where
   mempty = Transform 0 0 0
 
 -- | 2D transform component.
 --
--- @since 9.0
+-- @since 0.9
 type Transform2D = Transform (V2 Int) Int
 
 -- | Empty transform.
 --
--- @since 9.0
+-- @since 0.9
 transform2d :: Transform2D
 transform2d = Transform (V2 0 0) 0 (V2 1 1)
 
--- | @since 9.0
+-- | @since 0.9
 instance Component (Transform (V2 Int) Int)
 
 -- | Size component.
 --
--- @since 9.0
+-- @since 0.9
 newtype Size v = Size {unSize :: v}
   deriving (Generic, NFData)
 
--- | @since 9.0
+-- | @since 0.9
 type Size2D = Size (V2 Int)
 
 -- | Empty size.
 --
--- @since 9.0
+-- @since 0.9
 size2D :: Size (V2 Integer)
 size2D = Size (V2 0 0)
 
--- | @since 9.0
+-- | @since 0.9
 instance Component (Size (V2 Int))
 
 -- | Propagate a hierarchy of transform components.
 --
--- @since 9.0
+-- @since 0.9
 propagateHierarchy :: (Component a, Monoid a) => Hierarchy a -> Hierarchy a
 propagateHierarchy = mapWithAccum (\_ t acc -> let t' = t <> acc in (t', t')) mempty
 
 -- | Propagate and update all hierarchies of transform components.
 --
--- @since 9.0
+-- @since 0.9
 update ::
   forall q s b m a.
   ( ArrowQueryReader q,
@@ -128,7 +128,7 @@
 
 -- | Propagate and update all hierarchies of transform components.
 --
--- @since 9.0
+-- @since 0.9
 update2d ::
   ( ArrowQueryReader q,
     ArrowDynamicQueryReader q,
@@ -140,7 +140,7 @@
 
 -- | Propagate all hierarchies of transform components.
 --
--- @since 9.0
+-- @since 0.9
 propagate ::
   ( ArrowQueryReader q,
     ArrowDynamicQueryReader q,
@@ -155,7 +155,7 @@
 
 -- | Propagate all hierarchies of `Transform2D` components.
 --
--- @since 9.0
+-- @since 0.9
 propagate2d ::
   ( ArrowQueryReader q,
     ArrowDynamicQueryReader q,
diff --git a/src/Aztecs/Window.hs b/src/Aztecs/Window.hs
--- a/src/Aztecs/Window.hs
+++ b/src/Aztecs/Window.hs
@@ -17,14 +17,14 @@
 
 -- | Window component.
 --
--- @since 9.0
+-- @since 0.9
 newtype Window = Window
   { -- | Window title.
     --
-    -- @since 9.0
+    -- @since 0.9
     windowTitle :: String
   }
   deriving (Show, Generic, NFData)
 
--- | @since 9.0
+-- | @since 0.9
 instance Component Window
