@@ -1,44 +1,101 @@
1−{-# LANGUAGE ExistentialQuantification, GADTs, ScopedTypeVariables, TypeFamilies, FlexibleInstances, MultiParamTypeClasses, GeneralizedNewtypeDeriving, RankNTypes, BangPatterns, UndecidableInstances, EmptyDataDecls, RecursiveDo, RoleAnnotations, FunctionalDependencies #-}
1+{-# LANGUAGE ExistentialQuantification, GADTs, ScopedTypeVariables, TypeFamilies, FlexibleInstances, MultiParamTypeClasses, GeneralizedNewtypeDeriving, RankNTypes, BangPatterns, UndecidableInstances, EmptyDataDecls, RecursiveDo, RoleAnnotations, FunctionalDependencies, FlexibleContexts #-}
22module Reflex.Host.Class where
33
44import Prelude hiding (mapM, mapM_, sequence, sequence_, foldl)
55
66import Reflex.Class
77
8−import Control.Monad.State.Strict hiding (mapM, mapM_, forM, forM_, sequence, sequence_)
9−import Control.Monad.Reader hiding (mapM, mapM_, forM, forM_, sequence, sequence_)
8+import Control.Monad.Fix
9+import Control.Monad.Trans
10+import Control.Monad.Reader (ReaderT())
11+import Control.Monad.Writer (WriterT())
12+import Control.Monad.Cont (ContT())
13+import Control.Monad.Except (ExceptT())
14+import Control.Monad.RWS (RWST())
15+import Control.Monad.State (StateT())
1016import Data.Dependent.Sum (DSum)
1117import Control.Monad.Ref
1218
13−class Reflex t => ReflexHost t where
19+-- | Framework implementation support class for the reflex implementation represented by @t@.
20+class (Reflex t, MonadReflexCreateTrigger t (HostFrame t), MonadSample t (HostFrame t), MonadHold t (HostFrame t), MonadFix (HostFrame t)) => ReflexHost t where
1421 type EventTrigger t :: * -> *
1522 type EventHandle t :: * -> *
1623 type HostFrame t :: * -> *
1724
25+-- | Monad that allows to read events' values.
1826class (ReflexHost t, Monad m) => MonadReadEvent t m | m -> t where
27+ -- | Read the value of an 'Event' from an 'EventHandle' (created by calling 'subscribeEvent').
28+ --
29+ -- After event propagation is done, all events can be in two states: either they are firing with some value or they are not firing.
30+ -- In the former case, this function returns @Just act@, where @act@ in an action to read the current value of
31+ -- the event. In the latter case, the function returns @Nothing@.
32+ --
33+ -- This function is normally used in the calllback for 'fireEventsAndRead'.
1934 readEvent :: EventHandle t a -> m (Maybe (m a))
2035
21−class (Monad m, ReflexHost t) => MonadReflexCreateTrigger t m | m -> t where
22− -- | Creates an original Event (one that is not based on any other event).
36+-- | A monad where new events feed from external sources can be created.
37+class Monad m => MonadReflexCreateTrigger t m | m -> t where
38+ -- | Creates a root 'Event' (one that is not based on any other event).
39+ --
2340 -- When a subscriber first subscribes to an event (building another event
24− -- that depends on the subscription) the given callback function is run by
25− -- passing a trigger. The event is then set up in IO. The callback
26− -- function returns an accompanying teardown action.
41+ -- that depends on the subscription) the given callback function is run and
42+ -- passed a trigger. The callback function can then set up the event source in IO.
43+ -- After this is done, the callback function must return an accompanying teardown action.
44+ --
2745 -- Any time between setup and teardown the trigger can be used to fire
28− -- the event.
46+ -- the event, by passing it to 'fireEventsAndRead'.
47+ --
48+ -- Note: An event may be set up multiple times. So after the teardown action is executed, the event may still be set up again in the future.
2949 newEventWithTrigger :: (EventTrigger t a -> IO (IO ())) -> m (Event t a)
3050
3151class (Monad m, ReflexHost t, MonadReflexCreateTrigger t m) => MonadReflexHost t m | m -> t where
52+ -- | Propagate some events firings and read the values of events afterwards.
53+ --
54+ -- This function will create a new frame to fire the given events. It will then update all
55+ -- dependent events and behaviors. After that is done, the given callback is executed which
56+ -- allows to read the final values of events and check whether they have fired in this frame or
57+ -- not.
58+ --
59+ -- All events that are given are fired at the same time.
60+ --
61+ -- This function is typically used in the main loop of a reflex framework implementation.
62+ -- The main loop waits for external events to happen (such as keyboard input or a mouse click)
63+ -- and then fires the corresponding events using this function. The read callback can be used
64+ -- to read output events and perform a corresponding response action to the external event.
3265 fireEventsAndRead :: [DSum (EventTrigger t)] -> (forall m'. (MonadReadEvent t m') => m' a) -> m a
33− subscribeEvent :: Event t a -> m (EventHandle t a) --TODO: Return a handle, and use them in fireEventsAnRead
34− runFrame :: PushM t a -> m a
66+
67+ -- | Subscribe to an event and set it up if needed.
68+ --
69+ -- This function will create a new 'EventHandle' from an 'Event'. This handle may then be used via
70+ -- 'readEvent' in the read callback of 'fireEventsAndRead'.
71+ --
72+ -- If the event wasn't subscribed to before (either manually or through a dependent event or behavior)
73+ -- then this function will cause the event and all dependencies of this event to be set up.
74+ -- For example, if the event was created by 'newEventWithTrigger', then it's callback will be executed.
75+ --
76+ -- It's safe to call this function multiple times.
77+ subscribeEvent :: Event t a -> m (EventHandle t a)
78+
79+ -- | Run a frame without any events firing.
80+ --
81+ -- This function should be used when you want to use 'sample' and 'hold' when no events are currently firing.
82+ -- Using this function in that case can improve performance, since the implementation can assume that no events
83+ -- are firing when 'sample' or 'hold' are called.
84+ --
85+ -- This function is commonly used to set up the basic event network when the application starts up.
3586 runHostFrame :: HostFrame t a -> m a
3687
88+-- | Like 'fireEventsAndRead', but without reading any events.
3789fireEvents :: MonadReflexHost t m => [DSum (EventTrigger t)] -> m ()
38−{-# INLINE fireEvents #-}
3990fireEvents dm = fireEventsAndRead dm $ return ()
91+{-# INLINE fireEvents #-}
4092
41−{-# INLINE newEventWithTriggerRef #-}
93+-- | Create a new event and store its trigger in an 'IORef' while it's active.
94+--
95+-- An event is only active between the set up (when it's first subscribed to) and the teardown phases (when noboby is subscribing the event anymore).
96+-- This function returns an Event and an 'IORef'. As long as the event is active, the 'IORef' will contain 'Just' the event trigger to
97+-- trigger this event. When the event is not active, the 'IORef' will contain 'Nothing'. This allows event sources to be more efficient,
98+-- since they don't need to produce events when nobody is listening.
4299newEventWithTriggerRef :: (MonadReflexCreateTrigger t m, MonadRef m, Ref m ~ Ref IO) => m (Event t a, Ref m (Maybe (EventTrigger t a)))
43100newEventWithTriggerRef = do
44101 rt <- newRef Nothing
@@ -46,17 +103,57 @@ newEventWithTriggerRef = do
46103 writeRef rt $ Just t
47104 return $ writeRef rt Nothing
48105 return (e, rt)
106+{-# INLINE newEventWithTriggerRef #-}
49107
50108--------------------------------------------------------------------------------
51109-- Instances
52110--------------------------------------------------------------------------------
53111
54−instance (Reflex t, MonadReflexCreateTrigger t m) => MonadReflexCreateTrigger t (ReaderT r m) where
112+instance MonadReflexCreateTrigger t m => MonadReflexCreateTrigger t (ReaderT r m) where
55113 newEventWithTrigger initializer = do
56114 lift $ newEventWithTrigger initializer
57115
58−instance (Reflex t, MonadReflexHost t m) => MonadReflexHost t (ReaderT r m) where
116+instance MonadReflexHost t m => MonadReflexHost t (ReaderT r m) where
117+ fireEventsAndRead dm a = lift $ fireEventsAndRead dm a
118+ subscribeEvent = lift . subscribeEvent
119+ runHostFrame = lift . runHostFrame
120+
121+instance (MonadReflexCreateTrigger t m, Monoid w) => MonadReflexCreateTrigger t (WriterT w m) where
122+ newEventWithTrigger = lift . newEventWithTrigger
123+
124+instance (MonadReflexHost t m, Monoid w) => MonadReflexHost t (WriterT w m) where
125+ fireEventsAndRead dm a = lift $ fireEventsAndRead dm a
126+ subscribeEvent = lift . subscribeEvent
127+ runHostFrame = lift . runHostFrame
128+
129+instance MonadReflexCreateTrigger t m => MonadReflexCreateTrigger t (StateT s m) where
130+ newEventWithTrigger = lift . newEventWithTrigger
131+
132+instance MonadReflexHost t m => MonadReflexHost t (StateT s m) where
133+ fireEventsAndRead dm a = lift $ fireEventsAndRead dm a
134+ subscribeEvent = lift . subscribeEvent
135+ runHostFrame = lift . runHostFrame
136+
137+instance MonadReflexCreateTrigger t m => MonadReflexCreateTrigger t (ContT r m) where
138+ newEventWithTrigger = lift . newEventWithTrigger
139+
140+instance MonadReflexHost t m => MonadReflexHost t (ContT r m) where
141+ fireEventsAndRead dm a = lift $ fireEventsAndRead dm a
142+ subscribeEvent = lift . subscribeEvent
143+ runHostFrame = lift . runHostFrame
144+
145+instance MonadReflexCreateTrigger t m => MonadReflexCreateTrigger t (ExceptT e m) where
146+ newEventWithTrigger = lift . newEventWithTrigger
147+
148+instance MonadReflexHost t m => MonadReflexHost t (ExceptT e m) where
149+ fireEventsAndRead dm a = lift $ fireEventsAndRead dm a
150+ subscribeEvent = lift . subscribeEvent
151+ runHostFrame = lift . runHostFrame
152+
153+instance (MonadReflexCreateTrigger t m, Monoid w) => MonadReflexCreateTrigger t (RWST r w s m) where
154+ newEventWithTrigger = lift . newEventWithTrigger
155+
156+instance (MonadReflexHost t m, Monoid w) => MonadReflexHost t (RWST r w s m) where
59157 fireEventsAndRead dm a = lift $ fireEventsAndRead dm a
60158 subscribeEvent = lift . subscribeEvent
61− runFrame = lift . runFrame
62159 runHostFrame = lift . runHostFrame