-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A fast ECS for game engine programming -- -- A fast ECS for game engine programming @package apecs @version 0.2.0.3 module Apecs.Types -- | An Entity is really just an Int. The type variable is used to keep -- track of reads and writes, but can be freely cast. newtype Entity c Entity :: Int -> Entity c [unEntity] :: Entity c -> Int -- | A slice is a list of entities, represented by a Data.Unbox.Vector of -- Ints. newtype Slice c Slice :: Vector Int -> Slice c [unSlice] :: Slice c -> Vector Int -- | A system is a newtype around `ReaderT w IO a`, where w is the -- game world variable. newtype System w a System :: ReaderT w IO a -> System w a [unSystem] :: System w a -> ReaderT w IO a -- | A component is defined by the type of its storage The storage in turn -- supplies runtime types for the component. For the component to be -- valid, its Storage must be in instance of Initializable. class Initializable (Storage c) => Component c where type Storage c = s | s -> c where { type family Storage c = s | s -> c; } -- | A world Has a component if it can produce its Storage class Component c => Has w c getStore :: Has w c => System w (Storage c) -- | Common for every storage. Represents a container that can be -- initialized. class Initializable s where type InitArgs s where { type family InitArgs s; } initStoreWith :: Initializable s => InitArgs s -> IO s -- | A store that is indexed by entities. class HasMembers s where explReset s = do { sl <- explMembers s; mapM_ (explDestroy s) sl } explImapM_ s ma = liftIO (explMembers s) >>= mapM_ ma . toList explImapM s ma = liftIO (explMembers s) >>= mapM ma . toList -- | Destroys the component for the given index. explDestroy :: HasMembers s => s -> Int -> IO () -- | Returns whether there is a component for the given index explExists :: HasMembers s => s -> Int -> IO Bool -- | Returns an unboxed vector of member indices explMembers :: HasMembers s => s -> IO (Vector Int) -- | Removes all components. Default implementation iterates over members -- and calls explDestroy. explReset :: HasMembers s => s -> IO () -- | Monadically iterates over member indices explImapM_ :: (HasMembers s, MonadIO m) => s -> (Int -> m a) -> m () -- | Monadically iterates over member indices explImapM :: (HasMembers s, MonadIO m) => s -> (Int -> m a) -> m [a] -- | Represents a safe access to c. A safe access is either a read -- that might fail, or a write that might delete. newtype Safe c Safe :: SafeRW (Storage c) -> Safe c [getSafe] :: Safe c -> SafeRW (Storage c) -- | Class of storages that associates components with entities. class HasMembers s => Store s where type SafeRW s type Stores s explModify s ety f = do { etyExists <- explExists s ety; when etyExists $ explGetUnsafe s ety >>= explSet s ety . f } explCmap s f = explMembers s >>= mapM_ (\ ety -> explModify s ety f) explCmapM_ s sys = do { sl <- liftIO $ explMembers s; forM_ sl $ \ ety -> do { x :: Stores s <- liftIO $ explGetUnsafe s ety; sys x } } explCimapM_ s sys = do { sl <- liftIO $ explMembers s; forM_ sl $ \ ety -> do { x :: Stores s <- liftIO $ explGetUnsafe s ety; sys (ety, x) } } explCmapM s sys = do { sl <- liftIO $ explMembers s; for (toList sl) $ \ ety -> do { x :: Stores s <- liftIO $ explGetUnsafe s ety; sys x } } explCimapM s sys = do { sl <- liftIO $ explMembers s; for (toList sl) $ \ ety -> do { x :: Stores s <- liftIO $ explGetUnsafe s ety; sys (ety, x) } } where { type family SafeRW s; type family Stores s; } -- | Unsafe index to the store. Undefined if the component does not exist explGetUnsafe :: Store s => s -> Int -> IO (Stores s) -- | Retrieves a component from the store explGet :: Store s => s -> Int -> IO (SafeRW s) -- | Writes a component explSet :: Store s => s -> Int -> Stores s -> IO () -- | Either writes or deletes a component explSetMaybe :: Store s => s -> Int -> SafeRW s -> IO () -- | Modifies an element in the store. explModify :: Store s => s -> Int -> (Stores s -> Stores s) -> IO () -- | Maps over all elements of this store. The default implementation can -- be replaced by an optimized one explCmap :: Store s => s -> (Stores s -> Stores s) -> IO () explCmapM_ :: (Store s, MonadIO m) => s -> (Stores s -> m a) -> m () explCimapM_ :: (Store s, MonadIO m) => s -> ((Int, Stores s) -> m a) -> m () explCmapM :: (Store s, MonadIO m) => s -> (Stores s -> m a) -> m [a] explCimapM :: (Store s, MonadIO m) => s -> ((Int, Stores s) -> m a) -> m [a] -- | A constraint that indicates that the runtime representation of -- c is c This will almost always be the case, but it -- _might_ not be so we need this constraint. type IsRuntime c = (Store (Storage c), Stores (Storage c) ~ c) -- | Class of storages for global values class GlobalRW s c where explGlobalModify s f = do { r <- explGlobalRead s; explGlobalWrite s (f r) } explGlobalRead :: GlobalRW s c => s -> IO c explGlobalWrite :: GlobalRW s c => s -> c -> IO () explGlobalModify :: GlobalRW s c => s -> (c -> c) -> IO () -- | Classes of queries q that can be performed on a store -- s. class Query q s -- | Returns a slice of the results of the query explSlice :: Query q s => s -> q -> IO (Vector Int) -- | Query that returns all members, equivalent to members data All All :: All -- | Casts for entities and slices class Cast a b cast :: Cast a b => a -> b instance Control.Monad.IO.Class.MonadIO (Apecs.Types.System w) instance GHC.Base.Applicative (Apecs.Types.System w) instance GHC.Base.Monad (Apecs.Types.System w) instance GHC.Base.Functor (Apecs.Types.System w) instance GHC.Base.Monoid (Apecs.Types.Slice c) instance GHC.Show.Show (Apecs.Types.Slice c) instance GHC.Show.Show (Apecs.Types.Entity c) instance GHC.Classes.Ord (Apecs.Types.Entity c) instance GHC.Classes.Eq (Apecs.Types.Entity c) instance Apecs.Types.HasMembers s => Apecs.Types.Query Apecs.Types.All s instance Apecs.Types.Cast (Apecs.Types.Entity a) (Apecs.Types.Entity b) instance Apecs.Types.Cast (Apecs.Types.Slice a) (Apecs.Types.Slice b) instance (Apecs.Types.Component a, Apecs.Types.Component b) => Apecs.Types.Component (a, b) instance (Apecs.Types.Has w a, Apecs.Types.Has w b) => Apecs.Types.Has w (a, b) instance (Apecs.Types.Initializable a, Apecs.Types.Initializable b) => Apecs.Types.Initializable (a, b) instance (Apecs.Types.HasMembers a, Apecs.Types.HasMembers b) => Apecs.Types.HasMembers (a, b) instance (Apecs.Types.Store a, Apecs.Types.Store b) => Apecs.Types.Store (a, b) instance (Apecs.Types.GlobalRW a ca, Apecs.Types.GlobalRW b cb) => Apecs.Types.GlobalRW (a, b) (ca, cb) instance (Apecs.Types.Component a, Apecs.Types.Component b, Apecs.Types.Component c) => Apecs.Types.Component (a, b, c) instance (Apecs.Types.Has w a, Apecs.Types.Has w b, Apecs.Types.Has w c) => Apecs.Types.Has w (a, b, c) instance (Apecs.Types.Initializable a, Apecs.Types.Initializable b, Apecs.Types.Initializable c) => Apecs.Types.Initializable (a, b, c) instance (Apecs.Types.HasMembers a, Apecs.Types.HasMembers b, Apecs.Types.HasMembers c) => Apecs.Types.HasMembers (a, b, c) instance (Apecs.Types.Store a, Apecs.Types.Store b, Apecs.Types.Store c) => Apecs.Types.Store (a, b, c) instance (Apecs.Types.GlobalRW a ca, Apecs.Types.GlobalRW b cb, Apecs.Types.GlobalRW c cc) => Apecs.Types.GlobalRW (a, b, c) (ca, cb, cc) module Apecs.System -- | Run a system with a game world runSystem :: System w a -> w -> IO a -- | Run a system with a game world runWith :: w -> System w a -> IO a -- | A slice containing all entities with component c owners :: forall w c. (Has w c, HasMembers (Storage c)) => System w (Slice c) -- | Returns whether the given entity has component c For -- composite components, this indicates whether the component has all its -- constituents exists :: forall w c. (Has w c, HasMembers (Storage c)) => Entity c -> System w Bool -- | Destroys the component c for the given entity destroy :: forall w c. (Has w c, HasMembers (Storage c)) => Entity c -> System w () -- | Removes all components. Equivalent to manually iterating and deleting, -- but usually optimized. resetStore :: forall w c p. (Has w c, HasMembers (Storage c)) => p c -> System w () -- | Gets the component for a given entity. This is a safe access, because -- the entity might not have the requested components. get :: forall w c. (Store (Storage c), Has w c) => Entity c -> System w (Safe c) -- | Writes a component to a given entity. Will overwrite existing -- components. set :: forall w c e. (IsRuntime c, Has w c) => Entity e -> c -> System w () -- | Same as set, but uses Safe to possibly delete a component setOrDelete :: forall w c. (IsRuntime c, Has w c) => Entity c -> Safe c -> System w () -- | Applies a function if possible. Equivalent to reading, mapping, and -- writing, but stores can provide optimized implementations. modify :: forall w c. (IsRuntime c, Has w c) => Entity c -> (c -> c) -> System w () -- | Monadically iterate a system over all entities that have that -- component. Note that writing to the store while iterating over it is -- undefined behaviour. imapM_ :: forall w c. (Has w c, HasMembers (Storage c)) => (Entity c -> System w ()) -> System w () -- | Monadically iterate a system over all entities that have that -- component. Note that writing to the store while iterating over it is -- undefined behaviour. imapM :: forall w c a. (Has w c, HasMembers (Storage c)) => (Entity c -> System w a) -> System w [a] -- | Maps a pure function over all components cmap :: forall world c. (IsRuntime c, Has world c) => (c -> c) -> System world () -- | mapM_ version of cmap cmapM_ :: forall w c. (Has w c, IsRuntime c) => (c -> System w ()) -> System w () -- | indexed cmapM_, also gives the current entity. cimapM_ :: forall w c. (Has w c, IsRuntime c) => ((Entity c, c) -> System w ()) -> System w () -- | mapM version of cmap. Can be used to get a list of entities cmapM :: forall w c a. (Has w c, IsRuntime c) => (c -> System w a) -> System w [a] -- | indexed cmapM, also gives the current entity. cimapM :: forall w c a. (Has w c, IsRuntime c) => ((Entity c, c) -> System w a) -> System w [a] -- | Maps a function that might delete its components cmap' :: forall world c. (Has world c, IsRuntime c) => (c -> Safe c) -> System world () -- | Maps a function over all entities with a r, and writes their -- w rmap :: forall world r w. (Has world w, Has world r, IsRuntime w, IsRuntime r) => (r -> w) -> System world () -- | Maps a function over all entities with a r, and writes or -- deletes their w rmap' :: forall world r w. (Has world w, Has world r, Store (Storage w), IsRuntime r) => (r -> Safe w) -> System world () -- | For all entities with a w, this map reads their r -- and writes their w wmap :: forall world r w. (Has world w, Has world r, IsRuntime w, IsRuntime r) => (Safe r -> w) -> System world () -- | For all entities with a w, this map reads their r -- and writes or deletes their w wmap' :: forall world r w. (Has world w, Has world r, Store (Storage w), IsRuntime r) => (Safe r -> Safe w) -> System world () -- | Performs a query slice :: forall w c q. (Query q (Storage c), Has w c) => q -> System w (Slice c) -- | Reads a global value readGlobal :: forall w c. (Has w c, GlobalRW (Storage c) c) => System w c -- | Writes a global value writeGlobal :: forall w c. (Has w c, GlobalRW (Storage c) c) => c -> System w () -- | Modifies a global value modifyGlobal :: forall w c. (Has w c, GlobalRW (Storage c) c) => (c -> c) -> System w () module Apecs.Stores -- | A map from Data.Intmap.Strict. O(n log(n)) for most operations. Yields -- safe runtime representations of type Maybe c. data Map c -- | A store that keeps membership, but holds no values. Produces -- flag runtime values. data Set c -- | Class for flags, used by Set to yield runtime -- representations. class Flag c flag :: Flag c => c -- | A cache around another store. The wrapped store must produce safe -- representations using Maybe. Note that iterating over a cache is -- linear in its size, so large, sparsely populated caches will actually -- decrease performance. data Cache (n :: Nat) s -- | Global value. Must be given an initial value upon construction. data Global c -- | A table that keeps a hashtable of indices along with its writes. TODO: -- Benchmark? hashing function as argument? data IndexTable s -- | A component that can be hashed to a table index. minBound must hash to -- the lowest possible value, maxBound must hash to the highest. For -- Enums, toIndex = fromEnum class Bounded a => ToIndex a toIndex :: ToIndex a => a -> Int -- | A query to an IndexTable by an explicit index newtype ByIndex a ByIndex :: Int -> ByIndex a -- | A query to an IndexTable by a reference component newtype ByComponent c ByComponent :: c -> ByComponent c instance Apecs.Types.Initializable (Apecs.Stores.Map c) instance Apecs.Types.HasMembers (Apecs.Stores.Map c) instance Apecs.Types.Store (Apecs.Stores.Map c) instance Apecs.Types.Initializable (Apecs.Stores.Set c) instance Apecs.Types.HasMembers (Apecs.Stores.Set c) instance Apecs.Stores.Flag c => Apecs.Types.Store (Apecs.Stores.Set c) instance Apecs.Types.Initializable (Apecs.Stores.Const c) instance Apecs.Types.GlobalRW (Apecs.Stores.Const c) c instance Apecs.Types.HasMembers (Apecs.Stores.Const c) instance Apecs.Types.Store (Apecs.Stores.Const c) instance Apecs.Types.Initializable (Apecs.Stores.Global c) instance Apecs.Types.GlobalRW (Apecs.Stores.Global c) c instance (GHC.TypeLits.KnownNat n, Apecs.Types.Initializable s) => Apecs.Types.Initializable (Apecs.Stores.Cache n s) instance Apecs.Types.HasMembers s => Apecs.Types.HasMembers (Apecs.Stores.Cache n s) instance (Apecs.Types.SafeRW s ~ GHC.Base.Maybe (Apecs.Types.Stores s), Apecs.Types.Store s) => Apecs.Types.Store (Apecs.Stores.Cache n s) instance (Apecs.Stores.ToIndex (Apecs.Types.Stores s), Apecs.Types.Initializable s) => Apecs.Types.Initializable (Apecs.Stores.IndexTable s) instance (Apecs.Types.SafeRW s ~ GHC.Base.Maybe (Apecs.Types.Stores s), Apecs.Stores.ToIndex (Apecs.Types.Stores s), Apecs.Types.Store s) => Apecs.Types.HasMembers (Apecs.Stores.IndexTable s) instance (Apecs.Types.SafeRW s ~ GHC.Base.Maybe (Apecs.Types.Stores s), Apecs.Stores.ToIndex (Apecs.Types.Stores s), Apecs.Types.Store s) => Apecs.Types.Store (Apecs.Stores.IndexTable s) instance (Apecs.Types.Stores s ~ c, Apecs.Stores.ToIndex (Apecs.Types.Stores s)) => Apecs.Types.Query (Apecs.Stores.ByComponent c) (Apecs.Stores.IndexTable s) instance (Apecs.Types.Stores s ~ c, Apecs.Stores.ToIndex (Apecs.Types.Stores s)) => Apecs.Types.Query (Apecs.Stores.ByIndex c) (Apecs.Stores.IndexTable s) module Apecs.Util -- | Initializes a store with (), useful since most stores have () as their -- initialization argument initStore :: (Initializable s, InitArgs s ~ ()) => IO s -- | Sequentially performs a series of queries and concatenates their -- result. Especially useful when iterating over an IndexTable newtype ConcatQueries q ConcatQueries :: [q] -> ConcatQueries q -- | Explicitly invoke the garbage collector runGC :: System w () -- | Secretly just an int in a newtype data EntityCounter -- | Initialize an EntityCounter initCounter :: IO (Storage EntityCounter) -- | Bumps the EntityCounter and yields its value nextEntity :: Has w EntityCounter => System w (Entity ()) -- | Writes the given components to a new entity, and yields that entity newEntity :: (IsRuntime c, Has w c, Has w EntityCounter) => c -> System w (Entity c) -- | The following functions are for spatial hashing. The idea is that your -- spatial hash is defined by two vectors; - The cell size vector -- contains real components and dictates how large each cell in your -- table is spatially. It is used to translate from world-space to table -- space - The field size vector contains integral components and -- dictates how many cells your field consists of in each direction. It -- is used to translate from table-space to a flat integer -- -- Quantize turns a world-space coordinate into a table-space coordinate -- by dividing by the given cell size and round components towards -- negative infinity quantize :: (Fractional (v a), Integral b, RealFrac a, Functor v) => v a -> v a -> v b -- | Turns a table-space vector into a linear index, given some table size -- vector. flatten :: (Applicative v, Integral a, Foldable v) => v a -> v a -> a -- | For two table-space vectors indicating a region's bounds, gives a list -- of the vectors contained between them. This is useful for querying a -- spatial hash. region :: (Enum a, Applicative v, Traversable v) => v a -> v a -> [v a] -- | Tests whether a vector is in the region given by 0 and the size vector inbounds :: (Num (v a), Ord a, Applicative v, Foldable v) => v a -> v a -> Bool -- | Runs a system and gives its execution time in seconds timeSystem :: System w a -> System w (Double, a) -- | Runs a system, discards its output, and gives its execution time in -- seconds timeSystem_ :: System w a -> System w Double instance GHC.Show.Show Apecs.Util.EntityCounter instance GHC.Classes.Eq Apecs.Util.EntityCounter instance GHC.Num.Num Apecs.Util.EntityCounter instance Apecs.Types.Component Apecs.Util.EntityCounter instance Apecs.Types.Query q s => Apecs.Types.Query (Apecs.Util.ConcatQueries q) s module Apecs.Slice -- | Slice version of foldM_ sliceFoldM_ :: (a -> Entity c -> System w a) -> a -> Slice b -> System w () -- | Gets the size of a slice (O(n)) sliceSize :: Slice a -> Int -- | Tests whether a slice is empty (O(1)) sliceNull :: Slice a -> Bool -- | Construct a slice from a list of IDs sliceFromList :: [Int] -> Slice a -- | Monadically filter a slice sliceFilterM :: (Entity c -> System w Bool) -> Slice c -> System w (Slice c) -- | Concatenates two slices. Equivalent to mappend sliceConcat :: Slice a -> Slice b -> Slice c -- | Slice version of forM_ sliceForM_ :: Monad m => Slice c -> (Entity c -> m b) -> m () -- | Slice version of forM sliceForM :: Monad m => Slice c -> (Entity c -> m a) -> m [a] -- | Iterates over a slice, and reads the components of the Slice's type -- argument. sliceForMC :: forall w c a. (Store (Storage c), Has w c) => Slice c -> ((Entity c, Safe c) -> System w a) -> System w [a] -- | Iterates over a slice, and reads the components of the Slice's type -- argument. sliceForMC_ :: forall w c a. (Store (Storage c), Has w c) => Slice c -> ((Entity c, Safe c) -> System w a) -> System w () -- | Slice version of mapM_ sliceMapM_ :: Monad m => (Entity c -> m a) -> Slice c -> m () -- | Slice version of mapM sliceMapM :: Monad m => (Entity c -> m a) -> Slice c -> m [a] -- | Iterates over a slice, and reads the components of the Slice's type -- argument. sliceMapMC :: forall w c a. (Store (Storage c), Has w c) => ((Entity c, Safe c) -> System w a) -> Slice c -> System w [a] -- | Iterates over a slice, and reads the components of the Slice's type -- argument. sliceMapMC_ :: forall w c a. (Store (Storage c), Has w c) => ((Entity c, Safe c) -> System w a) -> Slice c -> System w () module Apecs -- | A system is a newtype around `ReaderT w IO a`, where w is the -- game world variable. newtype System w a System :: ReaderT w IO a -> System w a [unSystem] :: System w a -> ReaderT w IO a -- | A component is defined by the type of its storage The storage in turn -- supplies runtime types for the component. For the component to be -- valid, its Storage must be in instance of Initializable. class Initializable (Storage c) => Component c where type Storage c = s | s -> c where { type family Storage c = s | s -> c; } -- | An Entity is really just an Int. The type variable is used to keep -- track of reads and writes, but can be freely cast. newtype Entity c Entity :: Int -> Entity c [unEntity] :: Entity c -> Int -- | A slice is a list of entities, represented by a Data.Unbox.Vector of -- Ints. data Slice c -- | A world Has a component if it can produce its Storage class Component c => Has w c getStore :: Has w c => System w (Storage c) -- | Represents a safe access to c. A safe access is either a read -- that might fail, or a write that might delete. newtype Safe c Safe :: SafeRW (Storage c) -> Safe c [getSafe] :: Safe c -> SafeRW (Storage c) cast :: Cast a b => a -> b initStoreWith :: Initializable s => InitArgs s -> IO s -- | Destroys the component c for the given entity destroy :: forall w c. (Has w c, HasMembers (Storage c)) => Entity c -> System w () -- | Returns whether the given entity has component c For -- composite components, this indicates whether the component has all its -- constituents exists :: forall w c. (Has w c, HasMembers (Storage c)) => Entity c -> System w Bool -- | A slice containing all entities with component c owners :: forall w c. (Has w c, HasMembers (Storage c)) => System w (Slice c) -- | Removes all components. Equivalent to manually iterating and deleting, -- but usually optimized. resetStore :: forall w c p. (Has w c, HasMembers (Storage c)) => p c -> System w () -- | Gets the component for a given entity. This is a safe access, because -- the entity might not have the requested components. get :: forall w c. (Store (Storage c), Has w c) => Entity c -> System w (Safe c) -- | Writes a component to a given entity. Will overwrite existing -- components. set :: forall w c e. (IsRuntime c, Has w c) => Entity e -> c -> System w () -- | Same as set, but uses Safe to possibly delete a component setOrDelete :: forall w c. (IsRuntime c, Has w c) => Entity c -> Safe c -> System w () -- | Applies a function if possible. Equivalent to reading, mapping, and -- writing, but stores can provide optimized implementations. modify :: forall w c. (IsRuntime c, Has w c) => Entity c -> (c -> c) -> System w () -- | Maps a pure function over all components cmap :: forall world c. (IsRuntime c, Has world c) => (c -> c) -> System world () -- | mapM version of cmap. Can be used to get a list of entities cmapM :: forall w c a. (Has w c, IsRuntime c) => (c -> System w a) -> System w [a] -- | mapM_ version of cmap cmapM_ :: forall w c. (Has w c, IsRuntime c) => (c -> System w ()) -> System w () -- | indexed cmapM, also gives the current entity. cimapM :: forall w c a. (Has w c, IsRuntime c) => ((Entity c, c) -> System w a) -> System w [a] -- | indexed cmapM_, also gives the current entity. cimapM_ :: forall w c. (Has w c, IsRuntime c) => ((Entity c, c) -> System w ()) -> System w () -- | Maps a function over all entities with a r, and writes or -- deletes their w rmap' :: forall world r w. (Has world w, Has world r, Store (Storage w), IsRuntime r) => (r -> Safe w) -> System world () -- | Maps a function over all entities with a r, and writes their -- w rmap :: forall world r w. (Has world w, Has world r, IsRuntime w, IsRuntime r) => (r -> w) -> System world () -- | For all entities with a w, this map reads their r -- and writes their w wmap :: forall world r w. (Has world w, Has world r, IsRuntime w, IsRuntime r) => (Safe r -> w) -> System world () -- | For all entities with a w, this map reads their r -- and writes or deletes their w wmap' :: forall world r w. (Has world w, Has world r, Store (Storage w), IsRuntime r) => (Safe r -> Safe w) -> System world () -- | Maps a function that might delete its components cmap' :: forall world c. (Has world c, IsRuntime c) => (c -> Safe c) -> System world () -- | Reads a global value readGlobal :: forall w c. (Has w c, GlobalRW (Storage c) c) => System w c -- | Writes a global value writeGlobal :: forall w c. (Has w c, GlobalRW (Storage c) c) => c -> System w () -- | Modifies a global value modifyGlobal :: forall w c. (Has w c, GlobalRW (Storage c) c) => (c -> c) -> System w () -- | Performs a query slice :: forall w c q. (Query q (Storage c), Has w c) => q -> System w (Slice c) -- | Query that returns all members, equivalent to members data All All :: All -- | Run a system with a game world runSystem :: System w a -> w -> IO a -- | Run a system with a game world runWith :: w -> System w a -> IO a -- | Retrieves a function of the current environment. asks :: MonadReader r m => (r -> a) -> m a -- | Retrieves the monad environment. ask :: MonadReader r m => m r -- | Lift a computation from the IO monad. liftIO :: MonadIO m => forall a. IO a -> m a -- | Lift a computation from the argument monad to the constructed monad. lift :: MonadTrans t => forall (m :: * -> *) a. Monad m => m a -> t m a