-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A GHC.Generics based entity component system. -- -- Ecstasy is an entity-component system for Haskell. It's inspired by -- apecs, but makes the design decision to focus on being -- idiomatic rather than being fast. Maybe. I haven't actually -- benchmarked it. -- -- We achieve being idiomatic by using GHC.Generics and tricky -- type families to derive performant data stores given only a record of -- the desired components. @package ecstasy @version 0.2.0.1 module Data.Ecstasy.Types -- | The key for an entity. newtype Ent Ent :: Int -> Ent [unEnt] :: Ent -> Int -- | The internal state of the SystemT monad. type SystemState w m = (Int, w ( 'WorldOf m)) -- | A monad transformer over an ECS given a world w. newtype SystemT w m a SystemT :: StateT (SystemState w m) m a -> SystemT w m a [runSystemT'] :: SystemT w m a -> StateT (SystemState w m) m a -- | A monad over an ECS given a world w. type System w = SystemT w Identity -- | A computation to run over a particular entity. newtype QueryT w m a QueryT :: ReaderT (Ent, w 'FieldOf) (MaybeT m) a -> QueryT w m a [runQueryT'] :: QueryT w m a -> ReaderT (Ent, w 'FieldOf) (MaybeT m) a -- | A collection of methods necessary to dispatch reads and writes to a -- Virtual component. data VTable m a VTable :: !(Ent -> m (Maybe a)) -> !(Ent -> Update a -> m ()) -> VTable m a -- | Get the value of an entity's component. [vget] :: VTable m a -> !(Ent -> m (Maybe a)) -- | Update the value of an entity's component. [vset] :: VTable m a -> !(Ent -> Update a -> m ()) -- | Data kind used to parameterize the ECS record. data StorageType -- | Used to describe the actual entity. FieldOf :: StorageType -- | Used to construct the world's storage. WorldOf :: (Type -> Type) -> StorageType -- | Used to construct a setter to update an entity. SetterOf :: StorageType -- | Data kind used to parameterize the fields of the ECS record. data ComponentType -- | This component can be owned by any entity. Field :: ComponentType -- | This component can be owned by only a single entity at a time. Unique :: ComponentType -- | This component is owned by another system. Virtual :: ComponentType -- | Describes how we can change an a. data Update a -- | Keep the current value. Keep :: Update a -- | Delete the current value if it exists. Unset :: Update a -- | Set the current value. Set :: !a -> Update a -- | A type family to be used in your ECS recrod. instance Data.Traversable.Traversable Data.Ecstasy.Types.Update instance Data.Foldable.Foldable Data.Ecstasy.Types.Update instance GHC.Base.Functor Data.Ecstasy.Types.Update instance GHC.Read.Read a => GHC.Read.Read (Data.Ecstasy.Types.Update a) instance GHC.Show.Show a => GHC.Show.Show (Data.Ecstasy.Types.Update a) instance GHC.Classes.Ord a => GHC.Classes.Ord (Data.Ecstasy.Types.Update a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.Ecstasy.Types.Update a) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Data.Ecstasy.Types.SystemT w m) instance Control.Monad.Writer.Class.MonadWriter ww m => Control.Monad.Writer.Class.MonadWriter ww (Data.Ecstasy.Types.SystemT w m) instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Data.Ecstasy.Types.SystemT w m) instance GHC.Base.Monad m => GHC.Base.Monad (Data.Ecstasy.Types.SystemT w m) instance GHC.Base.Monad m => GHC.Base.Applicative (Data.Ecstasy.Types.SystemT w m) instance GHC.Base.Functor m => GHC.Base.Functor (Data.Ecstasy.Types.SystemT w m) instance GHC.Base.Monad m => GHC.Base.MonadPlus (Data.Ecstasy.Types.QueryT w m) instance GHC.Base.Monad m => GHC.Base.Alternative (Data.Ecstasy.Types.QueryT w m) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Data.Ecstasy.Types.QueryT w m) instance Control.Monad.Writer.Class.MonadWriter ww m => Control.Monad.Writer.Class.MonadWriter ww (Data.Ecstasy.Types.QueryT w m) instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Data.Ecstasy.Types.QueryT w m) instance GHC.Base.Monad m => GHC.Base.Monad (Data.Ecstasy.Types.QueryT w m) instance GHC.Base.Monad m => GHC.Base.Applicative (Data.Ecstasy.Types.QueryT w m) instance GHC.Base.Functor m => GHC.Base.Functor (Data.Ecstasy.Types.QueryT w m) instance GHC.Classes.Ord Data.Ecstasy.Types.Ent instance GHC.Classes.Eq Data.Ecstasy.Types.Ent instance Control.Monad.Trans.Class.MonadTrans (Data.Ecstasy.Types.SystemT w) instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Data.Ecstasy.Types.SystemT w m) instance Control.Monad.Trans.Class.MonadTrans (Data.Ecstasy.Types.QueryT w) instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Data.Ecstasy.Types.QueryT w m) instance GHC.Show.Show Data.Ecstasy.Types.Ent module Data.Ecstasy.Internal.Deriving class GConvertSetter a b gConvertSetter :: GConvertSetter a b => a x -> b x class GGetEntity m a b gGetEntity :: GGetEntity m a b => a x -> Int -> m (b x) class GSetEntity m a b gSetEntity :: GSetEntity m a b => a x -> Int -> b x -> m (b x) def :: forall keep a. (Generic a, GDefault keep (Rep a)) => a class GDefault (keep :: Bool) f gdef :: GDefault keep f => f a instance Data.Ecstasy.Internal.Deriving.GDefault keep GHC.Generics.U1 instance Data.Ecstasy.Internal.Deriving.GDefault keep (GHC.Generics.K1 i (GHC.Base.Maybe c)) instance Data.Ecstasy.Internal.Deriving.GDefault 'GHC.Types.False (GHC.Generics.K1 i (Data.Ecstasy.Types.Update c)) instance Data.Ecstasy.Internal.Deriving.GDefault 'GHC.Types.True (GHC.Generics.K1 i (Data.Ecstasy.Types.Update c)) instance Data.Ecstasy.Internal.Deriving.GDefault keep (GHC.Generics.K1 i (Data.IntMap.Internal.IntMap c)) instance (GHC.Base.Applicative m, GHC.TypeLits.KnownSymbol sym) => Data.Ecstasy.Internal.Deriving.GDefault keep (GHC.Generics.M1 GHC.Generics.S ('GHC.Generics.MetaSel ('GHC.Base.Just sym) x y z) (GHC.Generics.K1 i (Data.Ecstasy.Types.VTable m a))) instance Data.Ecstasy.Internal.Deriving.GDefault keep f => Data.Ecstasy.Internal.Deriving.GDefault keep (GHC.Generics.M1 i c f) instance (Data.Ecstasy.Internal.Deriving.GDefault keep a, Data.Ecstasy.Internal.Deriving.GDefault keep b) => Data.Ecstasy.Internal.Deriving.GDefault keep (a GHC.Generics.:*: b) instance GHC.Base.Applicative m => Data.Ecstasy.Internal.Deriving.GSetEntity m (GHC.Generics.K1 i (Data.Ecstasy.Types.Update a)) (GHC.Generics.K1 i' (GHC.Base.Maybe (GHC.Types.Int, a))) instance GHC.Base.Applicative m => Data.Ecstasy.Internal.Deriving.GSetEntity m (GHC.Generics.K1 i (Data.Ecstasy.Types.Update a)) (GHC.Generics.K1 i' (Data.Ecstasy.Types.VTable m a)) instance GHC.Base.Applicative m => Data.Ecstasy.Internal.Deriving.GSetEntity m (GHC.Generics.K1 i (Data.Ecstasy.Types.Update a)) (GHC.Generics.K1 i' (Data.IntMap.Internal.IntMap a)) instance (GHC.Base.Functor m, Data.Ecstasy.Internal.Deriving.GSetEntity m f f') => Data.Ecstasy.Internal.Deriving.GSetEntity m (GHC.Generics.M1 i c f) (GHC.Generics.M1 i' c' f') instance (GHC.Base.Applicative m, Data.Ecstasy.Internal.Deriving.GSetEntity m a c, Data.Ecstasy.Internal.Deriving.GSetEntity m b d) => Data.Ecstasy.Internal.Deriving.GSetEntity m (a GHC.Generics.:*: b) (c GHC.Generics.:*: d) instance GHC.Base.Applicative m => Data.Ecstasy.Internal.Deriving.GGetEntity m (GHC.Generics.K1 i (Data.Ecstasy.Types.VTable m a)) (GHC.Generics.K1 i' (GHC.Base.Maybe a)) instance GHC.Base.Applicative m => Data.Ecstasy.Internal.Deriving.GGetEntity m (GHC.Generics.K1 i (Data.IntMap.Internal.IntMap a)) (GHC.Generics.K1 i' (GHC.Base.Maybe a)) instance GHC.Base.Applicative m => Data.Ecstasy.Internal.Deriving.GGetEntity m (GHC.Generics.K1 i (GHC.Base.Maybe (GHC.Types.Int, a))) (GHC.Generics.K1 i' (GHC.Base.Maybe a)) instance (GHC.Base.Functor m, Data.Ecstasy.Internal.Deriving.GGetEntity m f f') => Data.Ecstasy.Internal.Deriving.GGetEntity m (GHC.Generics.M1 i c f) (GHC.Generics.M1 i' c' f') instance (GHC.Base.Applicative m, Data.Ecstasy.Internal.Deriving.GGetEntity m a c, Data.Ecstasy.Internal.Deriving.GGetEntity m b d) => Data.Ecstasy.Internal.Deriving.GGetEntity m (a GHC.Generics.:*: b) (c GHC.Generics.:*: d) instance Data.Ecstasy.Internal.Deriving.GConvertSetter (GHC.Generics.K1 i a) (GHC.Generics.K1 i' (GHC.Base.Maybe a)) instance Data.Ecstasy.Internal.Deriving.GConvertSetter (GHC.Generics.K1 i a) (GHC.Generics.K1 i' (Data.Ecstasy.Types.Update a)) instance Data.Ecstasy.Internal.Deriving.GConvertSetter (GHC.Generics.K1 i (GHC.Base.Maybe a)) (GHC.Generics.K1 i' (Data.Ecstasy.Types.Update a)) instance Data.Ecstasy.Internal.Deriving.GConvertSetter f f' => Data.Ecstasy.Internal.Deriving.GConvertSetter (GHC.Generics.M1 i c f) (GHC.Generics.M1 i' c' f') instance (Data.Ecstasy.Internal.Deriving.GConvertSetter a c, Data.Ecstasy.Internal.Deriving.GConvertSetter b d) => Data.Ecstasy.Internal.Deriving.GConvertSetter (a GHC.Generics.:*: b) (c GHC.Generics.:*: d) module Data.Ecstasy.Internal -- | This class provides all of the functionality necessary to manipulate -- the ECS. class HasWorld' world => HasWorld world m -- | Fetches an entity from the world given its Ent. getEntity :: (HasWorld world m, Monad m) => Ent -> SystemT world m (world 'FieldOf) -- | Fetches an entity from the world given its Ent. getEntity :: (HasWorld world m, Monad m, GGetEntity m (Rep (world ( 'WorldOf m))) (Rep (world 'FieldOf)), Generic (world 'FieldOf), Generic (world ( 'WorldOf m))) => Ent -> SystemT world m (world 'FieldOf) -- | Updates an Ent in the world given its setter. setEntity :: HasWorld world m => Ent -> world 'SetterOf -> SystemT world m () -- | Updates an Ent in the world given its setter. setEntity :: (HasWorld world m, GSetEntity m (Rep (world 'SetterOf)) (Rep (world ( 'WorldOf m))), Generic (world ( 'WorldOf m)), Generic (world 'SetterOf), Monad m) => Ent -> world 'SetterOf -> SystemT world m () -- | The default world, which contains only empty containers. defStorage :: HasWorld world m => world ( 'WorldOf m) -- | The default world, which contains only empty containers. defStorage :: (HasWorld world m, Generic (world ( 'WorldOf m)), GDefault 'True (Rep (world ( 'WorldOf m)))) => world ( 'WorldOf m) class HasWorld' world -- | Transforms an entity into a setter to transform the default entity -- into the given one. Used by createEntity. convertSetter :: HasWorld' world => world 'FieldOf -> world 'SetterOf -- | Transforms an entity into a setter to transform the default entity -- into the given one. Used by createEntity. convertSetter :: (HasWorld' world, GConvertSetter (Rep (world 'FieldOf)) (Rep (world 'SetterOf)), Generic (world 'FieldOf), Generic (world 'SetterOf)) => world 'FieldOf -> world 'SetterOf -- | The default entity, owning no components. newEntity :: HasWorld' world => world 'FieldOf -- | The default entity, owning no components. newEntity :: (HasWorld' world, Generic (world 'FieldOf), GDefault 'True (Rep (world 'FieldOf))) => world 'FieldOf -- | The default setter, which keeps all components with their previous -- value. unchanged :: HasWorld' world => world 'SetterOf -- | The default setter, which keeps all components with their previous -- value. unchanged :: (HasWorld' world, Generic (world 'SetterOf), GDefault 'True (Rep (world 'SetterOf))) => world 'SetterOf -- | A setter which will delete the entity if its QueryT matches. delEntity :: HasWorld' world => world 'SetterOf -- | A setter which will delete the entity if its QueryT matches. delEntity :: (HasWorld' world, Generic (world 'SetterOf), GDefault 'False (Rep (world 'SetterOf))) => world 'SetterOf -- | Retrieve a unique Ent. nextEntity :: Monad m => SystemT a m Ent -- | Create a new entity. createEntity :: (HasWorld world m, Monad m) => world 'FieldOf -> SystemT world m Ent -- | Delete an entity. deleteEntity :: (HasWorld world m, Monad m) => Ent -> SystemT world m () -- | Evaluate a QueryT. unQueryT :: QueryT world m a -> Ent -> world 'FieldOf -> m (Maybe a) -- | Map a QueryT transformation over all entites that match it. emap :: (HasWorld world m, Monad m) => EntTarget world m -> QueryT world m (world 'SetterOf) -> SystemT world m () -- | Collect the results of a monadic computation over every entity -- matching a QueryT. efor :: (HasWorld world m, Monad m) => EntTarget world m -> QueryT world m a -> SystemT world m [a] -- | Do an emap and an efor at the same time. eover :: (HasWorld world m, Monad m) => EntTarget world m -> QueryT world m (a, world 'SetterOf) -> SystemT world m [a] -- | Run a QueryT over a particular Ent. runQueryT :: (HasWorld world m, Monad m) => Ent -> QueryT world m a -> SystemT world m (Maybe a) -- | Provides a resumable SystemT. This is a pretty big hack until I -- come up with a better formalization for everything. yieldSystemT :: Monad m => SystemState world m -> SystemT world m a -> m (SystemState world m, a) -- | Evaluate a SystemT. runSystemT :: Monad m => world ( 'WorldOf m) -> SystemT world m a -> m a -- | Evaluate a System. runSystem :: world ( 'WorldOf Identity) -> System world a -> a -- | Only evaluate this QueryT for entities which have the given -- component. with :: Monad m => (world 'FieldOf -> Maybe a) -> QueryT world m () -- | Only evaluate this QueryT for entities which do not have the -- given component. without :: Monad m => (world 'FieldOf -> Maybe a) -> QueryT world m () -- | Get the value of a component, failing the QueryT if it isn't -- present. query :: Monad m => (world 'FieldOf -> Maybe a) -> QueryT world m a -- | Attempt to get the value of a component. queryMaybe :: Monad m => (world 'FieldOf -> Maybe a) -> QueryT world m (Maybe a) -- | Get the Ent for whom this query is running. queryEnt :: Monad m => QueryT world m Ent -- | Query a flag as a Bool. queryFlag :: Monad m => (world 'FieldOf -> Maybe ()) -> QueryT world m Bool -- | Perform a query with a default. queryDef :: Monad m => z -> (world 'FieldOf -> Maybe z) -> QueryT world m z -- | An EntTarget is a set of Ents to iterate over. type EntTarget world m = SystemT world m [Ent] -- | Iterate over all entities. allEnts :: Monad m => EntTarget world m -- | Iterate over some entities. someEnts :: Monad m => [Ent] -> EntTarget world m -- | Iterate over an entity. anEnt :: Monad m => Ent -> EntTarget world m -- | Turn a Maybe into an Update. maybeToUpdate :: Maybe a -> Update a instance (Data.Ecstasy.Internal.HasWorld' world, GHC.Generics.Generic (world 'Data.Ecstasy.Types.SetterOf), GHC.Generics.Generic (world ('Data.Ecstasy.Types.WorldOf m)), GHC.Generics.Generic (world 'Data.Ecstasy.Types.FieldOf), Data.Ecstasy.Internal.Deriving.GConvertSetter (GHC.Generics.Rep (world 'Data.Ecstasy.Types.FieldOf)) (GHC.Generics.Rep (world 'Data.Ecstasy.Types.SetterOf)), Data.Ecstasy.Internal.Deriving.GDefault 'GHC.Types.True (GHC.Generics.Rep (world 'Data.Ecstasy.Types.FieldOf)), Data.Ecstasy.Internal.Deriving.GDefault 'GHC.Types.False (GHC.Generics.Rep (world 'Data.Ecstasy.Types.SetterOf)), Data.Ecstasy.Internal.Deriving.GDefault 'GHC.Types.True (GHC.Generics.Rep (world 'Data.Ecstasy.Types.SetterOf)), Data.Ecstasy.Internal.Deriving.GDefault 'GHC.Types.True (GHC.Generics.Rep (world ('Data.Ecstasy.Types.WorldOf m))), Data.Ecstasy.Internal.Deriving.GSetEntity m (GHC.Generics.Rep (world 'Data.Ecstasy.Types.SetterOf)) (GHC.Generics.Rep (world ('Data.Ecstasy.Types.WorldOf m))), Data.Ecstasy.Internal.Deriving.GGetEntity m (GHC.Generics.Rep (world ('Data.Ecstasy.Types.WorldOf m))) (GHC.Generics.Rep (world 'Data.Ecstasy.Types.FieldOf)), GHC.Base.Monad m) => Data.Ecstasy.Internal.HasWorld world m instance (GHC.Generics.Generic (world 'Data.Ecstasy.Types.SetterOf), GHC.Generics.Generic (world 'Data.Ecstasy.Types.FieldOf), Data.Ecstasy.Internal.Deriving.GConvertSetter (GHC.Generics.Rep (world 'Data.Ecstasy.Types.FieldOf)) (GHC.Generics.Rep (world 'Data.Ecstasy.Types.SetterOf)), Data.Ecstasy.Internal.Deriving.GDefault 'GHC.Types.True (GHC.Generics.Rep (world 'Data.Ecstasy.Types.FieldOf)), Data.Ecstasy.Internal.Deriving.GDefault 'GHC.Types.False (GHC.Generics.Rep (world 'Data.Ecstasy.Types.SetterOf)), Data.Ecstasy.Internal.Deriving.GDefault 'GHC.Types.True (GHC.Generics.Rep (world 'Data.Ecstasy.Types.SetterOf))) => Data.Ecstasy.Internal.HasWorld' world -- | Ecstasy is a library architected around the HKD pattern, the -- gist of which is to define a "template" type that can be reused for -- several purposes. Users of ecstasy should define a record type of -- Components parameterized over a variable of kind -- StorageType: -- --
-- data World s = Entity
-- { position :: Component s 'Field (V2 Double)
-- , graphics :: Component s 'Field Graphics
-- , isPlayer :: Component s 'Unique ()
-- }
-- deriving (Generic)
--
--
-- Ensure that this type have an instance of Generic.
--
-- For usability, it might be desirable to also define the following type
-- synonym:
--
-- -- type Entity = World 'FieldOf ---- -- which is the only form of the World that most users of -- ecstasy will need to interact with. -- -- Throughout this document there are references to the HasWorld -- and HasWorld' classes, which are implementation details and -- provided automatically by the library. module Data.Ecstasy -- | Data kind used to parameterize the fields of the ECS record. data ComponentType -- | This component can be owned by any entity. Field :: ComponentType -- | This component can be owned by only a single entity at a time. Unique :: ComponentType -- | This component is owned by another system. Virtual :: ComponentType -- | A type family to be used in your ECS recrod. -- | The default world, which contains only empty containers. defStorage :: HasWorld world m => world ( 'WorldOf m) -- | Data kind used to parameterize the ECS record. data StorageType -- | Used to describe the actual entity. FieldOf :: StorageType -- | Used to construct the world's storage. WorldOf :: (Type -> Type) -> StorageType -- | Used to construct a setter to update an entity. SetterOf :: StorageType -- | A monad transformer over an ECS given a world w. data SystemT w m a -- | Evaluate a SystemT. runSystemT :: Monad m => world ( 'WorldOf m) -> SystemT world m a -> m a -- | Provides a resumable SystemT. This is a pretty big hack until I -- come up with a better formalization for everything. yieldSystemT :: Monad m => SystemState world m -> SystemT world m a -> m (SystemState world m, a) -- | A monad over an ECS given a world w. type System w = SystemT w Identity -- | Evaluate a System. runSystem :: world ( 'WorldOf Identity) -> System world a -> a -- | The internal state of the SystemT monad. type SystemState w m = (Int, w ( 'WorldOf m)) -- | Create a new entity. createEntity :: (HasWorld world m, Monad m) => world 'FieldOf -> SystemT world m Ent -- | The default entity, owning no components. newEntity :: HasWorld' world => world 'FieldOf -- | Fetches an entity from the world given its Ent. getEntity :: (HasWorld world m, Monad m) => Ent -> SystemT world m (world 'FieldOf) -- | Updates an Ent in the world given its setter. setEntity :: HasWorld world m => Ent -> world 'SetterOf -> SystemT world m () -- | Delete an entity. deleteEntity :: (HasWorld world m, Monad m) => Ent -> SystemT world m () -- | Map a QueryT transformation over all entites that match it. emap :: (HasWorld world m, Monad m) => EntTarget world m -> QueryT world m (world 'SetterOf) -> SystemT world m () -- | Collect the results of a monadic computation over every entity -- matching a QueryT. efor :: (HasWorld world m, Monad m) => EntTarget world m -> QueryT world m a -> SystemT world m [a] -- | Do an emap and an efor at the same time. eover :: (HasWorld world m, Monad m) => EntTarget world m -> QueryT world m (a, world 'SetterOf) -> SystemT world m [a] -- | The default setter, which keeps all components with their previous -- value. unchanged :: HasWorld' world => world 'SetterOf -- | A setter which will delete the entity if its QueryT matches. delEntity :: HasWorld' world => world 'SetterOf -- | An EntTarget is a set of Ents to iterate over. type EntTarget world m = SystemT world m [Ent] -- | Iterate over all entities. allEnts :: Monad m => EntTarget world m -- | Iterate over some entities. someEnts :: Monad m => [Ent] -> EntTarget world m -- | Iterate over an entity. anEnt :: Monad m => Ent -> EntTarget world m -- | A computation to run over a particular entity. data QueryT w m a -- | Run a QueryT over a particular Ent. runQueryT :: (HasWorld world m, Monad m) => Ent -> QueryT world m a -> SystemT world m (Maybe a) -- | Get the value of a component, failing the QueryT if it isn't -- present. query :: Monad m => (world 'FieldOf -> Maybe a) -> QueryT world m a -- | Only evaluate this QueryT for entities which have the given -- component. with :: Monad m => (world 'FieldOf -> Maybe a) -> QueryT world m () -- | Only evaluate this QueryT for entities which do not have the -- given component. without :: Monad m => (world 'FieldOf -> Maybe a) -> QueryT world m () -- | Get the Ent for whom this query is running. queryEnt :: Monad m => QueryT world m Ent -- | Attempt to get the value of a component. queryMaybe :: Monad m => (world 'FieldOf -> Maybe a) -> QueryT world m (Maybe a) -- | Query a flag as a Bool. queryFlag :: Monad m => (world 'FieldOf -> Maybe ()) -> QueryT world m Bool -- | Perform a query with a default. queryDef :: Monad m => z -> (world 'FieldOf -> Maybe z) -> QueryT world m z -- | Describes how we can change an a. data Update a -- | Keep the current value. Keep :: Update a -- | Delete the current value if it exists. Unset :: Update a -- | Set the current value. Set :: !a -> Update a -- | Turn a Maybe into an Update. maybeToUpdate :: Maybe a -> Update a -- | The key for an entity. data Ent -- | A collection of methods necessary to dispatch reads and writes to a -- Virtual component. data VTable m a VTable :: !(Ent -> m (Maybe a)) -> !(Ent -> Update a -> m ()) -> VTable m a -- | Get the value of an entity's component. [vget] :: VTable m a -> !(Ent -> m (Maybe a)) -- | Update the value of an entity's component. [vset] :: VTable m a -> !(Ent -> Update a -> m ()) -- | Representable types of kind *. This class is derivable in GHC with the -- DeriveGeneric flag on. class Generic a