on develop help sign in
Some minor tweaks to the documentation
commit6a8c8fc0e3ce48eab05173d5467d98574c32a7f3 authorRyan Trinkle <ryan.trinkle@gmail.com> dateThu 30 Apr 2015, 02:34 (11 years ago) parent654e433
1 file changed+37−15
src/Reflex/Dynamic.hs+37−15
src/Reflex/Dynamic.hs+37−15
@@ -89,7 +89,8 @@ instance HBuild' (a ': l) r
8989 hBuild' l x = hBuild' (HCons x l)
9090
9191-- | A container for a value that can change over time and allows notifications on changes.
92−-- Basically a combination of a 'Behavior' and an 'Event'.
92+-- Basically a combination of a 'Behavior' and an 'Event', with a rule that the Behavior will
93+-- change if and only if the Event fires.
9394data Dynamic t a
9495 = Dynamic (Behavior t a) (Event t a)
9596
@@ -135,11 +136,12 @@ instance Reflex t => Functor (Dynamic t) where
135136mapDyn :: (Reflex t, MonadHold t m) => (a -> b) -> Dynamic t a -> m (Dynamic t b)
136137mapDyn f = mapDynM $ return . f
137138
138−-- | Flipped version of 'forDyn'.
139+-- | Flipped version of 'mapDyn'.
139140forDyn :: (Reflex t, MonadHold t m) => Dynamic t a -> (a -> b) -> m (Dynamic t b)
140141forDyn = flip mapDyn
141142
142−-- | Map a monadic function over a 'Dynamic'.
143+-- | Map a monadic function over a 'Dynamic'. The only monadic action that the given function can
144+-- perform is 'sample'.
143145{-# INLINE mapDynM #-}
144146mapDynM :: forall t m a b. (Reflex t, MonadHold t m) => (forall m'. MonadSample t m' => a -> m' b) -> Dynamic t a -> m (Dynamic t b)
145147mapDynM f d = do
@@ -177,7 +179,8 @@ toggle :: (Reflex t, MonadHold t m, MonadFix m) => Bool -> Event t a -> m (Dynam
177179toggle = foldDyn (const not)
178180
179181-- | Switches to the new 'Event' whenever it receives one. Switching
180−-- occurs *before* occurring the inner 'Event'.
182+-- occurs *before* the inner 'Event' fires - so if the 'Dynamic' changes and both the old and new
183+-- inner Events fire simultaneously, the output will fire with the value of the *new* 'Event'.
181184switchPromptlyDyn :: forall t a. Reflex t => Dynamic t (Event t a) -> Event t a
182185switchPromptlyDyn de =
183186 let eLag = switch $ current de
@@ -293,12 +296,18 @@ joinDynThroughMap dd =
293296
294297-- | Print the value of the 'Dynamic' on each change and prefix it
295298-- with the provided string. This should /only/ be used for debugging.
299+--
300+-- Note: Just like Debug.Trace.trace, the value will only be shown if something
301+-- else in the system is depending on it.
296302traceDyn :: (Reflex t, Show a) => String -> Dynamic t a -> Dynamic t a
297303traceDyn s = traceDynWith $ \x -> s <> ": " <> show x
298304
299305-- | Print the result of applying the provided function to the value
300306-- of the 'Dynamic' on each change. This should /only/ be used for
301307-- debugging.
308+--
309+-- Note: Just like Debug.Trace.trace, the value will only be shown if something
310+-- else in the system is depending on it.
302311traceDynWith :: Reflex t => (a -> String) -> Dynamic t a -> Dynamic t a
303312traceDynWith f d =
304313 let e' = traceEventWith f $ updated d
@@ -306,22 +315,36 @@ traceDynWith f d =
306315
307316-- | Replace the value of the 'Event' with the current value of the 'Dynamic'
308317-- each time the 'Event' occurs.
318+--
319+-- Note: `tagDyn d e` differs from `tag (current d) e` in the case that `e` is firing
320+-- at the same time that `d` is changing. With `tagDyn d e`, the *new* value of `d`
321+-- will replace the value of `e`, whereas with `tag (current d) e`, the *old* value
322+-- will be used, since the 'Behavior' won't be updated until the end of the frame.
323+-- Additionally, this means that the output 'Event' may not be used to directly change
324+-- the input 'Dynamic', because that would mean its value depends on itself. When creating
325+-- cyclic data flows, generally `tag (current d) e` is preferred.
309326tagDyn :: Reflex t => Dynamic t a -> Event t b -> Event t a
310327tagDyn = attachDynWith const
311328
312329-- | Attach the current value of the 'Dynamic' to the value of the
313330-- 'Event' each time it occurs.
331+--
332+-- Note: `attachDyn d` is not the same as `attach (current d)`. See 'tagDyn' for details.
314333attachDyn :: Reflex t => Dynamic t a -> Event t b -> Event t (a, b)
315334attachDyn = attachDynWith (,)
316335
317336-- | Combine the current value of the 'Dynamic' with the value of the
318337-- 'Event' each time it occurs.
338+--
339+-- Note: `attachDynWith f d` is not the same as `attachWith f (current d)`. See 'tagDyn' for details.
319340attachDynWith :: Reflex t => (a -> b -> c) -> Dynamic t a -> Event t b -> Event t c
320341attachDynWith f = attachDynWithMaybe $ \a b -> Just $ f a b
321342
322343-- | Create a new 'Event' by combining the value at each occurence
323344-- with the current value of the 'Dynamic' value and possibly
324345-- filtering if the combining function returns 'Nothing'.
346+--
347+-- Note: `attachDynWithMaybe f d` is not the same as `attachWithMaybe f (current d)`. See 'tagDyn' for details.
325348attachDynWithMaybe :: Reflex t => (a -> b -> Maybe c) -> Dynamic t a -> Event t b -> Event t c
326349attachDynWithMaybe f d e =
327350 let e' = attach (current d) e
@@ -335,25 +358,24 @@ attachDynWithMaybe f d e =
335358--------------------------------------------------------------------------------
336359
337360-- | Represents a time changing value together with an 'EventSelector'
338−-- for changes to this value.
361+-- that can efficiently detect when the underlying Dynamic has a particular value.
362+-- This is useful for representing data like the current selection of a long list.
363+--
364+-- Semantically,
365+-- > getDemuxed (demux d) k === mapDyn (== k) d
366+-- However, the when getDemuxed is used multiple times, the complexity is only /O(log(n))/,
367+-- rather than /O(n)/ for mapDyn.
339368data Demux t k = Demux { demuxValue :: Behavior t k
340369 , demuxSelector :: EventSelector t (Const2 k Bool)
341370 }
342371
343−-- | Create 'Demux' out of a 'Dynamic' that has the value of the
344−-- 'Dynamic' and allows selecting between the values of the 'Event'
345−-- and the 'Behavior' of the 'Dynamic' for the occurences of 'Event'
346−-- where they differ. Selecting the value of the 'Behavior' will
347−-- return 'False' while selecting the value of the 'Event' will return
348−-- 'True'.
372+-- | Demultiplex an input value to a 'Demux' with many outputs. At any given time, whichever output is indicated by the given 'Dynamic' will be 'True'.
349373demux :: (Reflex t, Ord k) => Dynamic t k -> Demux t k
350374demux k = Demux (current k) (fan $ attachWith (\k0 k1 -> if k0 == k1 then DMap.empty else DMap.fromList [Const2 k0 :=> False, Const2 k1 :=> True]) (current k) (updated k))
351375
352376--TODO: The pattern of using hold (sample b0) can be reused in various places as a safe way of building certain kinds of Dynamics; see if we can factor this out
353−-- | Extract the 'Event' of the 'Demux' for the supplied value and
354−-- create a 'Dynamic' with the initial value of the equality of the
355−-- 'Behavior' and the supplied value. Each occurence of the extracted
356−-- 'Event' changes the value of the 'Dynamic'.
377+-- | Select a particular output of the 'Demux'; this is equivalent to (but much faster than)
378+-- mapping over the original 'Dynamic' and checking whether it is equal to the given key.
357379getDemuxed :: (Reflex t, MonadHold t m, Eq k) => Demux t k -> k -> m (Dynamic t Bool)
358380getDemuxed d k = do
359381 let e = select (demuxSelector d) (Const2 k)