module Eve ( eve , eveT , App , Action , AppT , ActionT , liftAction , AppState -- * Events , dispatchEvent , dispatchEvent_ , dispatchEventAsync , dispatchActionAsync , addListener , addListener_ , removeListener -- * Working with Async Events/Actions , asyncActionProvider , asyncEventProvider , Dispatcher , Listener , ListenerId -- * Built-in Event Listeners , onInit , afterInit , beforeEvent , beforeEvent_ , afterEvent , afterEvent_ , onExit -- * Working with State -- | All application-provided states are stored in the same -- Map; keyed by their 'Data.Typeable.TypeRep'. This means that if more than one state -- uses the same type then they'll conflict and overwrite each-other (this is less of a -- problem than you're probably thinking). This is easily solved by simply -- using a newtype around any types you haven't defined yourself. -- For example if your application stores a counter as an Int, wrap it in your own custom -- @Counter@ newtype when storing it. If you wish to store multiple copies of a given state -- simply store them in a list or map, then store that container as your state. -- -- Because states are stored by their 'Data.Typeable.TypeRep', they must define an -- instance of 'Data.Typeable.Typeable', luckily GHC can derive this for you with -- @deriving Typeable@. -- -- It is also required for all states to define an instance of -- 'Data.Default.Default', this is because accessing an extension which has not -- yet been stored will result in the default value. -- -- If there's no default value that makes sense for your type, you can define -- a default of 'Data.Maybe.Nothing' and pattern-match on its value when you -- access it. -- -- Stored states are accessed by using the `stateLens` lens, this lens is polymorphic -- and can return ANY type. GHC infers the needed type and the lens will retrieve the -- state that you want from the store of states. It seems a bit complicated, but it all -- works fine in practice. -- -- To avoid confusion it's best to rename a version of `stateLens` with a more restrictive -- type for each different state type that you store. This helps prevent strange errors and -- makes your code much easier to read. For example: -- -- > data MyState = MyState String -- > myState :: HasStates s => Lens' s MyState -- > myState = stateLens -- > -- > myAction = do -- > MyState str <- use stateLens -- -- If GHC has trouble inferring the type, rename it and restrict the type as above. , HasStates(..) , States , HasEvents , stateLens , runAction , exit ) where import Eve.Internal.Run import Eve.Internal.Actions import Eve.Internal.Listeners import Eve.Internal.Async import Eve.Internal.AppState import Eve.Internal.States