@@ -1,5 +1,6 @@
1−{-# LANGUAGE ConstraintKinds #-}
1+{-# LANGUAGE BangPatterns #-}
2{-# LANGUAGE CPP #-}
2{-# LANGUAGE CPP #-}
3+{-# LANGUAGE ConstraintKinds #-}
3{-# LANGUAGE DefaultSignatures #-}
4{-# LANGUAGE DefaultSignatures #-}
4{-# LANGUAGE FlexibleContexts #-}
5{-# LANGUAGE FlexibleContexts #-}
5{-# LANGUAGE FlexibleInstances #-}
6{-# LANGUAGE FlexibleInstances #-}
@@ -8,6 +9,7 @@
8{-# LANGUAGE LambdaCase #-}
9{-# LANGUAGE LambdaCase #-}
9{-# LANGUAGE MultiParamTypeClasses #-}
10{-# LANGUAGE MultiParamTypeClasses #-}
10{-# LANGUAGE NoMonomorphismRestriction #-}
11{-# LANGUAGE NoMonomorphismRestriction #-}
12+{-# LANGUAGE PolyKinds #-}
11{-# LANGUAGE RankNTypes #-}
13{-# LANGUAGE RankNTypes #-}
12{-# LANGUAGE RecursiveDo #-}
14{-# LANGUAGE RecursiveDo #-}
13{-# LANGUAGE RoleAnnotations #-}
15{-# LANGUAGE RoleAnnotations #-}
@@ -18,14 +20,14 @@
18#ifdef USE_REFLEX_OPTIMIZER
20#ifdef USE_REFLEX_OPTIMIZER
19{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
21{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
21−#ifdef SPECIALIZE_TO_SPIDERTIMELINE_GLOBAL
22−{-# LANGUAGE EmptyDataDecls #-}
23−{-# OPTIONS_GHC -Wno-redundant-constraints #-}
26−-- | This module contains the Reflex interface, as well as a variety of
28+-- This module contains the Reflex interface, as well as a variety of
27−-- convenience functions for working with 'Event's, 'Behavior's, and other
29+-- convenience functions for working with 'Event's, 'Behavior's, and other
28−-- signals.
30+-- signals.
29module Reflex.Class
31module Reflex.Class
30 ( module Reflex.Patch
32 ( module Reflex.Patch
31 -- * Primitives
33 -- * Primitives
@@ -36,19 +38,22 @@ module Reflex.Class
36 , coerceDynamic
38 , coerceDynamic
37 , MonadSample (..)
39 , MonadSample (..)
38 , MonadHold (..)
40 , MonadHold (..)
39− -- ** 'fan'-related types
41+ -- ** 'fan' related types
40 , EventSelector (..)
42 , EventSelector (..)
41 , EventSelectorInt (..)
43 , EventSelectorInt (..)
42− -- ** 'Incremental'-related types
43 -- * Convenience functions
44 -- * Convenience functions
44 , constDyn
45 , constDyn
45 , pushAlways
46 , pushAlways
46 -- ** Combining 'Event's
47 -- ** Combining 'Event's
47 , leftmost
48 , leftmost
48 , mergeMap
49 , mergeMap
49 , mergeMapIncremental
51 , mergeMapIncremental
50 , mergeMapIncrementalWithMove
52 , mergeMapIncrementalWithMove
51 , mergeIntMapIncremental
53 , mergeIntMapIncremental
54+ , coincidencePatchMap
55+ , coincidencePatchMapWithMove
56+ , coincidencePatchIntMap
52 , mergeList
57 , mergeList
53 , mergeWith
58 , mergeWith
54 , difference
59 , difference
@@ -62,11 +67,16 @@ module Reflex.Class
62 , EitherTag (..)
67 , EitherTag (..)
63 , eitherToDSum
68 , eitherToDSum
64 , dsumToEither
69 , dsumToEither
65− -- ** Switching between 'Event's
70+ , factorEvent
66− , switchPromptly
71+ , filterEventKey
67− , switchPromptOnly
72+ -- ** Collapsing 'Event . Event'
75+ , switchHoldPromptOnly
76+ , switchHoldPromptOnlyIncremental
68 -- ** Using 'Event's to sample 'Behavior's
77 -- ** Using 'Event's to sample 'Behavior's
71 , attachWith
81 , attachWith
72 , attachWithMaybe
82 , attachWithMaybe
@@ -100,6 +110,14 @@ module Reflex.Class
100 , mapAccumM_
110 , mapAccumM_
101 , mapAccumMaybe_
111 , mapAccumMaybe_
102 , mapAccumMaybeM_
112 , mapAccumMaybeM_
115+ , accumMaybeIncremental
116+ , accumMaybeMIncremental
117+ , mapAccumIncremental
118+ , mapAccumMIncremental
119+ , mapAccumMaybeIncremental
120+ , mapAccumMaybeMIncremental
103 , zipListWithEvent
121 , zipListWithEvent
104 , numberOccurrences
122 , numberOccurrences
105 , numberOccurrencesFrom
123 , numberOccurrencesFrom
@@ -109,6 +127,9 @@ module Reflex.Class
110 , headTailE
128 , headTailE
111 , takeWhileE
129 , takeWhileE
132+ , takeDropWhileJustE
112 , switcher
133 , switcher
113 -- * Debugging functions
134 -- * Debugging functions
114 , traceEvent
135 , traceEvent
@@ -116,25 +137,24 @@ module Reflex.Class
116 -- * Unsafe functions
137 -- * Unsafe functions
117 , unsafeDynamic
138 , unsafeDynamic
118 , unsafeMapIncremental
139 , unsafeMapIncremental
119− -- * 'FunctorMaybe'
140+ -- * 'Filterable' convenience functions
120− , FunctorMaybe (..)
141+ , FunctorMaybe -- fmapMaybe is purposely not exported from deprecated 'FunctorMaybe' and the new alias is exported instead
142+ , mapMaybe -- Re-exported for convenience
121 , fforMaybe
144 , fforMaybe
122 , ffilter
145 , ffilter
123 , filterLeft
146 , filterLeft
124 , filterRight
147 , filterRight
127− , sequenceDMapWithAdjust
128− , sequenceDMapWithAdjustWithMove
129− , mapMapWithAdjustWithMove
130 -- * Miscellaneous convenience functions
148 -- * Miscellaneous convenience functions
132 -- * Deprecated functions
152 -- * Deprecated functions
133− , MonadAdjust
153+ , switchPromptly
134− , appendEvents
154+ , switchPromptOnly
135− , onceE
155+ -- * "Cheap" functions
137 , fmapMaybeCheap
156 , fmapMaybeCheap
138 , fmapCheap
158 , fmapCheap
139 , fforCheap
159 , fforCheap
140 , fforMaybeCheap
160 , fforMaybeCheap
@@ -144,97 +164,51 @@ module Reflex.Class
144 , mergeWithCheap'
164 , mergeWithCheap'
145 -- * Slow, but general, implementations
165 -- * Slow, but general, implementations
146 , slowHeadE
166 , slowHeadE
147−#ifdef SPECIALIZE_TO_SPIDERTIMELINE_GLOBAL
167− , unsafeBuildDynamic
168− , unsafeBuildIncremental
170− , mergeIncrementalWithMove
171− , currentIncremental
172− , updatedIncremental
173− , incrementalToDynamic
180import Control.Applicative
169import Control.Applicative
181−import Control.Monad.Identity hiding (forM, forM_, mapM, mapM_, sequence, sequence_)
170+import Control.Monad.Identity
182−import Control.Monad.Reader hiding (forM, forM_, mapM, mapM_, sequence, sequence_)
171+import Control.Monad.Reader
183−import Control.Monad.State.Strict hiding (forM, forM_, mapM, mapM_, sequence, sequence_)
172+import Control.Monad.State.Strict
184−import Control.Monad.Trans.Cont (ContT ())
173+import Control.Monad.Trans.Cont (ContT)
185−import Control.Monad.Trans.Except (ExceptT ())
174+import Control.Monad.Trans.Except (ExceptT)
186−import Control.Monad.Trans.RWS (RWST ())
175+import Control.Monad.Trans.RWS (RWST)
187−import Control.Monad.Trans.Writer (WriterT ())
176+import Control.Monad.Trans.Writer (WriterT)
188import Data.Align
177import Data.Align
189import Data.Bifunctor
178import Data.Bifunctor
190import Data.Coerce
179import Data.Coerce
191import Data.Default
180import Data.Default
192−import Data.Dependent.Map (DMap, DSum (..), GCompare (..))
181+import Data.Dependent.Map (DMap, DSum (..))
193import qualified Data.Dependent.Map as DMap
182import qualified Data.Dependent.Map as DMap
194−import Data.Either
183+import Data.Functor.Compose
184+import Data.Functor.Product
185+import Data.GADT.Compare (GEq (..), GCompare (..), (:~:) (..))
186+import Data.FastMutableIntMap (PatchIntMap)
195import Data.Foldable
187import Data.Foldable
196−import Data.Functor.Bind hiding (join)
188+import Data.Functor.Bind
197−import qualified Data.Functor.Bind as Bind
198−import Data.Functor.Constant
199import Data.Functor.Misc
189import Data.Functor.Misc
200import Data.Functor.Plus
190import Data.Functor.Plus
201import Data.IntMap.Strict (IntMap)
191import Data.IntMap.Strict (IntMap)
202import qualified Data.IntMap.Strict as IntMap
192import qualified Data.IntMap.Strict as IntMap
203import Data.List.NonEmpty (NonEmpty (..))
193import Data.List.NonEmpty (NonEmpty (..))
204import Data.Map (Map)
194import Data.Map (Map)
206−import Data.Monoid hiding (Alt, (<>))
207import Data.Semigroup (Semigroup, sconcat, stimes, (<>))
195import Data.Semigroup (Semigroup, sconcat, stimes, (<>))
196+import Data.Some (Some)
197+import qualified Data.Some as Some
208import Data.String
198import Data.String
209import Data.These
199import Data.These
210−import Data.Traversable
211import Data.Type.Coercion
200import Data.Type.Coercion
201+import Data.Witherable (Filterable(..))
202+import qualified Data.Witherable as W
203+import Reflex.FunctorMaybe (FunctorMaybe)
212−import Reflex.FunctorMaybe
204+import qualified Reflex.FunctorMaybe
213import Reflex.Patch
205import Reflex.Patch
214−import Data.FastMutableIntMap (PatchIntMap)
206+import qualified Reflex.Patch.MapWithMove as PatchMapWithMove
216−#ifdef SPECIALIZE_TO_SPIDERTIMELINE_GLOBAL
217−import Reflex.Spider.Internal (EventM, Global, HasSpiderTimeline, SpiderHost (..), SpiderHostFrame (..),
218− SpiderPullM, SpiderPushM (..), behaviorHoldIdentity, dynamicConst,
219− dynamicCurrent, dynamicDynIdentity, dynamicHold, dynamicHoldIdentity,
220− dynamicUpdated, newMapDyn, readBehaviorTracked, readBehaviorUntracked,
221− runFrame, runSpiderHostFrame)
222−import qualified Reflex.Spider.Internal
223−import qualified Reflex.Spider.Internal as S
227−-- Note: must come last to silence warnings due to AMP on GHC < 7.10
228−import Prelude hiding (foldl, mapM, mapM_, sequence, sequence_)
230import Debug.Trace (trace)
208import Debug.Trace (trace)
232−#ifdef SPECIALIZE_TO_SPIDERTIMELINE_GLOBAL
233−#include "Spider/SpiderTimeline.include.hs"
236-- | The 'Reflex' class contains all the primitive functionality needed for
210-- | The 'Reflex' class contains all the primitive functionality needed for
237−-- Functional Reactive Programming (FRP). The @t@ type parameter indicates
211+-- Functional Reactive Programming (FRP). The @/t/@ type parameter indicates
238-- which "timeline" is in use. Timelines are fully-independent FRP contexts,
212-- which "timeline" is in use. Timelines are fully-independent FRP contexts,
239-- and the type of the timeline determines the FRP engine to be used. For most
213-- and the type of the timeline determines the FRP engine to be used. For most
240-- purposes, the 'Reflex.Spider' implementation is recommended.
214-- purposes, the 'Reflex.Spider' implementation is recommended.
@@ -244,9 +218,6 @@ class ( MonadHold t (PushM t)
244 , Functor (Dynamic t)
218 , Functor (Dynamic t)
245 , Applicative (Dynamic t) -- Necessary for GHC <= 7.8
219 , Applicative (Dynamic t) -- Necessary for GHC <= 7.8
246 , Monad (Dynamic t)
220 , Monad (Dynamic t)
247−#ifdef SPECIALIZE_TO_SPIDERTIMELINE_GLOBAL
248− , t ~ SpiderTimeline Global
250 ) => Reflex t where
221 ) => Reflex t where
251 -- | A container for a value that can change over time. 'Behavior's can be
222 -- | A container for a value that can change over time. 'Behavior's can be
252 -- sampled at will, but it is not possible to be notified when they change
223 -- sampled at will, but it is not possible to be notified when they change
@@ -269,7 +240,6 @@ class ( MonadHold t (PushM t)
269 type PushM t :: * -> *
240 type PushM t :: * -> *
270 -- | A monad for doing complex pull-based calculations efficiently
241 -- | A monad for doing complex pull-based calculations efficiently
271 type PullM t :: * -> *
242 type PullM t :: * -> *
272−#ifndef SPECIALIZE_TO_SPIDERTIMELINE_GLOBAL
273 -- | An 'Event' with no occurrences
243 -- | An 'Event' with no occurrences
274 never :: Event t a
244 never :: Event t a
275 -- | Create a 'Behavior' that always has the given value
245 -- | Create a 'Behavior' that always has the given value
@@ -284,7 +254,7 @@ class ( MonadHold t (PushM t)
284 -- recomputed whenever any of the read 'Behavior's changes
254 -- recomputed whenever any of the read 'Behavior's changes
285 pull :: PullM t a -> Behavior t a
255 pull :: PullM t a -> Behavior t a
286 -- | Merge a collection of events; the resulting 'Event' will only occur if at
256 -- | Merge a collection of events; the resulting 'Event' will only occur if at
287− -- least one input event is occuring, and will contain all of the input keys
257+ -- least one input event is occurring, and will contain all of the input keys
288 -- that are occurring simultaneously
258 -- that are occurring simultaneously
289 merge :: GCompare k => DMap k (Event t) -> Event t (DMap k Identity) --TODO: Generalize to get rid of DMap use --TODO: Provide a type-level guarantee that the result is not empty
259 merge :: GCompare k => DMap k (Event t) -> Event t (DMap k Identity) --TODO: Generalize to get rid of DMap use --TODO: Provide a type-level guarantee that the result is not empty
290 -- | Efficiently fan-out an event to many destinations. This function should
260 -- | Efficiently fan-out an event to many destinations. This function should
@@ -294,8 +264,7 @@ class ( MonadHold t (PushM t)
294 -- | Create an 'Event' that will occur whenever the currently-selected input
264 -- | Create an 'Event' that will occur whenever the currently-selected input
295 -- 'Event' occurs
265 -- 'Event' occurs
296 switch :: Behavior t (Event t a) -> Event t a
266 switch :: Behavior t (Event t a) -> Event t a
297− -- | Create an 'Event' that will occur whenever the input event is occurring
267+ -- | Create an 'Event' that will occur whenever the input event is occurring -- and its occurrence value, another 'Event', is also occurring
298− -- and its occurrence value, another 'Event', is also occurring
299 coincidence :: Event t (Event t a) -> Event t a
268 coincidence :: Event t (Event t a) -> Event t a
300 -- | Extract the 'Behavior' of a 'Dynamic'.
269 -- | Extract the 'Behavior' of a 'Dynamic'.
301 current :: Dynamic t a -> Behavior t a
270 current :: Dynamic t a -> Behavior t a
@@ -304,7 +273,7 @@ class ( MonadHold t (PushM t)
304 -- | Create a new 'Dynamic'. The given 'PullM' must always return the most
273 -- | Create a new 'Dynamic'. The given 'PullM' must always return the most
305 -- recent firing of the given 'Event', if any.
274 -- recent firing of the given 'Event', if any.
306 unsafeBuildDynamic :: PullM t a -> Event t a -> Dynamic t a
275 unsafeBuildDynamic :: PullM t a -> Event t a -> Dynamic t a
307− -- | Create a new 'Incremental'. The given 'PullM''s value must always change
276+ -- | Create a new 'Incremental'. The given "PullM"'s value must always change
308 -- in the same way that the accumulated application of patches would change
277 -- in the same way that the accumulated application of patches would change
309 -- that value.
278 -- that value.
310 unsafeBuildIncremental :: Patch p => PullM t (PatchTarget p) -> Event t p -> Incremental t p
279 unsafeBuildIncremental :: Patch p => PullM t (PatchTarget p) -> Event t p -> Incremental t p
@@ -329,84 +298,11 @@ class ( MonadHold t (PushM t)
329 dynamicCoercion :: Coercion a b -> Coercion (Dynamic t a) (Dynamic t b)
298 dynamicCoercion :: Coercion a b -> Coercion (Dynamic t a) (Dynamic t b)
330 mergeIntIncremental :: Incremental t (PatchIntMap (Event t a)) -> Event t (IntMap a)
299 mergeIntIncremental :: Incremental t (PatchIntMap (Event t a)) -> Event t (IntMap a)
331 fanInt :: Event t (IntMap a) -> EventSelectorInt t a
300 fanInt :: Event t (IntMap a) -> EventSelectorInt t a
334--TODO: Specialize this so that we can take advantage of knowing that there's no changing going on
302--TODO: Specialize this so that we can take advantage of knowing that there's no changing going on
335mergeInt :: Reflex t => IntMap (Event t a) -> Event t (IntMap a)
303mergeInt :: Reflex t => IntMap (Event t a) -> Event t (IntMap a)
336mergeInt m = mergeIntIncremental $ unsafeBuildIncremental (return m) never
304mergeInt m = mergeIntIncremental $ unsafeBuildIncremental (return m) never
338−#ifdef SPECIALIZE_TO_SPIDERTIMELINE_GLOBAL
339−instance t ~ SpiderTimeline Global => Reflex t where
340− newtype Behavior t a = SpiderBehavior { unSpiderBehavior :: Reflex.Spider.Internal.Behavior Global a }
341− newtype Event t a = SpiderEvent { unSpiderEvent :: Reflex.Spider.Internal.Event Global a }
342− newtype Dynamic t a = SpiderDynamic { unSpiderDynamic :: Reflex.Spider.Internal.Dynamic Global (Identity a) } -- deriving (Functor, Applicative, Monad)
343− newtype Incremental t p = SpiderIncremental { unSpiderIncremental :: Reflex.Spider.Internal.Dynamic Global p }
344− type PullM t = SpiderPullM Global
345− type PushM t = SpiderPushM Global
346−never :: Reflex t => Event t a
347−constant :: Reflex t => a -> Behavior t a
348−push :: Reflex t => (a -> PushM t (Maybe b)) -> Event t a -> Event t b
349−pushCheap :: Reflex t => (a -> PushM t (Maybe b)) -> Event t a -> Event t b
350−pull :: Reflex t => PullM t a -> Behavior t a
351−merge :: (Reflex t, GCompare k) => DMap k (Event t) -> Event t (DMap k Identity)
352−fan :: (Reflex t, GCompare k) => Event t (DMap k Identity) -> EventSelector t k
353−switch :: Reflex t => Behavior t (Event t a) -> Event t a
354−coincidence :: Reflex t => Event t (Event t a) -> Event t a
355−current :: Reflex t => Dynamic t a -> Behavior t a
356−updated :: Reflex t => Dynamic t a -> Event t a
357−unsafeBuildDynamic :: Reflex t => PullM t a -> Event t a -> Dynamic t a
358−unsafeBuildIncremental :: (Reflex t, Patch p) => PullM t (PatchTarget p) -> Event t p -> Incremental t p
359−mergeIncremental :: (Reflex t, GCompare k) => Incremental t (PatchDMap k (Event t)) -> Event t (DMap k Identity)
360−mergeIncrementalWithMove :: (Reflex t, GCompare k) => Incremental t (PatchDMapWithMove k (Event t)) -> Event t (DMap k Identity)
361−currentIncremental :: (Reflex t, Patch p) => Incremental t p -> Behavior t (PatchTarget p)
362−updatedIncremental :: (Reflex t, Patch p) => Incremental t p -> Event t p
363−incrementalToDynamic :: (Reflex t, Patch p) => Incremental t p -> Dynamic t (PatchTarget p)
364−behaviorCoercion :: Reflex t => Coercion a b -> Coercion (Behavior t a) (Behavior t b)
365−eventCoercion :: Reflex t => Coercion a b -> Coercion (Event t a) (Event t b)
366−dynamicCoercion :: Reflex t => Coercion a b -> Coercion (Dynamic t a) (Dynamic t b)
368−never = SpiderEvent S.eventNever
369−{-# INLINE constant #-}
370−constant = SpiderBehavior . S.behaviorConst
372−push f = SpiderEvent . S.push (coerce f) . unSpiderEvent
373−{-# INLINE pushCheap #-}
374−pushCheap f = SpiderEvent . S.pushCheap (coerce f) . unSpiderEvent
376−pull = SpiderBehavior . S.pull . coerce
378−merge = SpiderEvent . S.merge . S.dynamicConst . (coerce :: DMap k (Event (SpiderTimeline x)) -> DMap k (S.Event x))
380−fan e = EventSelector $ SpiderEvent . S.select (S.fan (unSpiderEvent e))
381−{-# INLINE switch #-}
382−switch = SpiderEvent . S.switch . (coerce :: S.Behavior x (Event (SpiderTimeline x) a) -> S.Behavior x (S.Event x a)) . unSpiderBehavior
383−{-# INLINE coincidence #-}
384−coincidence = SpiderEvent . S.coincidence . (coerce :: S.Event x (Event (SpiderTimeline x) a) -> S.Event x (S.Event x a)) . unSpiderEvent
385−{-# INLINE current #-}
386−current = SpiderBehavior . S.dynamicCurrent . unSpiderDynamic
387−{-# INLINE updated #-}
388−updated = coerceEvent . SpiderEvent . dynamicUpdated . unSpiderDynamic
389−{-# INLINE unsafeBuildDynamic #-}
390−unsafeBuildDynamic readV0 v' = SpiderDynamic $ dynamicDynIdentity $ S.unsafeBuildDynamic (coerce readV0) $ coerce $ unSpiderEvent v'
391−{-# INLINE unsafeBuildIncremental #-}
392−unsafeBuildIncremental readV0 dv = SpiderIncremental $ S.dynamicDyn $ S.unsafeBuildDynamic (coerce readV0) $ unSpiderEvent dv
393−{-# INLINE mergeIncremental #-}
394−mergeIncremental = SpiderEvent . S.merge . (unsafeCoerce :: S.Dynamic x (PatchDMap k (Event (SpiderTimeline x))) -> S.Dynamic x (PatchDMap k (S.Event x))) . unSpiderIncremental
395−{-# INLINE mergeIncrementalWithMove #-}
396−mergeIncrementalWithMove = SpiderEvent . S.mergeWithMove . (unsafeCoerce :: S.Dynamic x (PatchDMapWithMove k (Event (SpiderTimeline x))) -> S.Dynamic x (PatchDMapWithMove k (S.Event x))) . unSpiderIncremental
397−{-# INLINE currentIncremental #-}
398−currentIncremental = SpiderBehavior . dynamicCurrent . unSpiderIncremental
399−{-# INLINE updatedIncremental #-}
400−updatedIncremental = SpiderEvent . dynamicUpdated . unSpiderIncremental
401−{-# INLINE incrementalToDynamic #-}
402−incrementalToDynamic (SpiderIncremental i) = SpiderDynamic $ dynamicDynIdentity $ S.unsafeBuildDynamic (readBehaviorUntracked $ dynamicCurrent i) $ flip S.push (dynamicUpdated i) $ \p -> do
403− c <- readBehaviorUntracked $ dynamicCurrent i
404− return $ Identity <$> apply p c
405−eventCoercion Coercion = Coercion
406−behaviorCoercion Coercion = Coercion
407−dynamicCoercion = unsafeCoerce
410-- | Coerce a 'Behavior' between representationally-equivalent value types
306-- | Coerce a 'Behavior' between representationally-equivalent value types
411coerceBehavior :: (Reflex t, Coercible a b) => Behavior t a -> Behavior t b
307coerceBehavior :: (Reflex t, Coercible a b) => Behavior t a -> Behavior t b
412coerceBehavior = coerceWith $ behaviorCoercion Coercion
308coerceBehavior = coerceWith $ behaviorCoercion Coercion
@@ -420,7 +316,7 @@ coerceDynamic :: (Reflex t, Coercible a b) => Dynamic t a -> Dynamic t b
420coerceDynamic = coerceWith $ dynamicCoercion Coercion
316coerceDynamic = coerceWith $ dynamicCoercion Coercion
422-- | Construct a 'Dynamic' from a 'Behavior' and an 'Event'. The 'Behavior'
318-- | Construct a 'Dynamic' from a 'Behavior' and an 'Event'. The 'Behavior'
423−-- _must_ change when and only when the 'Event' fires, such that the
319+-- __must__ change when and only when the 'Event' fires, such that the
424-- 'Behavior''s value is always equal to the most recent firing of the 'Event';
320-- 'Behavior''s value is always equal to the most recent firing of the 'Event';
425-- if this is not the case, the resulting 'Dynamic' will behave
321-- if this is not the case, the resulting 'Dynamic' will behave
426-- nondeterministically.
322-- nondeterministically.
@@ -448,7 +344,7 @@ class MonadSample t m => MonadHold t m where
448 -- value and will be updated whenever the given 'Event' occurs. The update
344 -- value and will be updated whenever the given 'Event' occurs. The update
449 -- takes effect immediately after the 'Event' occurs; if the occurrence that
345 -- takes effect immediately after the 'Event' occurs; if the occurrence that
450 -- sets the 'Behavior' (or one that is simultaneous with it) is used to sample
346 -- sets the 'Behavior' (or one that is simultaneous with it) is used to sample
451− -- the 'Behavior', it will see the _old_ value of the 'Behavior', not the new
347+ -- the 'Behavior', it will see the __old__ value of the 'Behavior', not the new
453 hold :: a -> Event t a -> m (Behavior t a)
349 hold :: a -> Event t a -> m (Behavior t a)
454 default hold :: (m ~ f m', MonadTrans f, MonadHold t m') => a -> Event t a -> m (Behavior t a)
350 default hold :: (m ~ f m', MonadTrans f, MonadHold t m') => a -> Event t a -> m (Behavior t a)
@@ -463,15 +359,44 @@ class MonadSample t m => MonadHold t m where
463 holdIncremental :: Patch p => PatchTarget p -> Event t p -> m (Incremental t p)
359 holdIncremental :: Patch p => PatchTarget p -> Event t p -> m (Incremental t p)
464 default holdIncremental :: (Patch p, m ~ f m', MonadTrans f, MonadHold t m') => PatchTarget p -> Event t p -> m (Incremental t p)
360 default holdIncremental :: (Patch p, m ~ f m', MonadTrans f, MonadHold t m') => PatchTarget p -> Event t p -> m (Incremental t p)
465 holdIncremental v0 = lift . holdIncremental v0
361 holdIncremental v0 = lift . holdIncremental v0
466− buildDynamic :: PullM t a -> Event t a -> m (Dynamic t a)
362+ buildDynamic :: PushM t a -> Event t a -> m (Dynamic t a)
468 default buildDynamic :: (m ~ f m', MonadTrans f, MonadHold t m') => PullM t a -> Event t a -> m (Dynamic t a)
364 default buildDynamic :: (m ~ f m', MonadTrans f, MonadHold t m') => PullM t a -> Event t a -> m (Dynamic t a)
469 buildDynamic getV0 = lift . buildDynamic getV0
365 buildDynamic getV0 = lift . buildDynamic getV0
471− -- | Create a new 'Event' that only occurs only once, on the first occurence of
367+ -- | Create a new 'Event' that only occurs only once, on the first occurrence of
472 -- the supplied 'Event'.
368 -- the supplied 'Event'.
473 headE :: Event t a -> m (Event t a)
369 headE :: Event t a -> m (Event t a)
371+accumIncremental :: (Reflex t, Patch p, MonadHold t m, MonadFix m) => (PatchTarget p -> b -> p) -> PatchTarget p -> Event t b -> m (Incremental t p)
372+accumIncremental f = accumMaybeIncremental $ \v o -> Just $ f v o
373+accumMIncremental :: (Reflex t, Patch p, MonadHold t m, MonadFix m) => (PatchTarget p -> b -> PushM t p) -> PatchTarget p -> Event t b -> m (Incremental t p)
374+accumMIncremental f = accumMaybeMIncremental $ \v o -> Just <$> f v o
375+accumMaybeIncremental :: (Reflex t, Patch p, MonadHold t m, MonadFix m) => (PatchTarget p -> b -> Maybe p) -> PatchTarget p -> Event t b -> m (Incremental t p)
376+accumMaybeIncremental f = accumMaybeMIncremental $ \v o -> return $ f v o
377+accumMaybeMIncremental :: (Reflex t, Patch p, MonadHold t m, MonadFix m) => (PatchTarget p -> b -> PushM t (Maybe p)) -> PatchTarget p -> Event t b -> m (Incremental t p)
378+accumMaybeMIncremental f z e = do
379+ rec let e' = flip push e $ \o -> do
380+ v <- sample $ currentIncremental d'
382+ d' <- holdIncremental z e'
384+mapAccumIncremental :: (Reflex t, Patch p, MonadHold t m, MonadFix m) => (PatchTarget p -> b -> (p, c)) -> PatchTarget p -> Event t b -> m (Incremental t p, Event t c)
385+mapAccumIncremental f = mapAccumMaybeIncremental $ \v o -> bimap Just Just $ f v o
386+mapAccumMIncremental :: (Reflex t, Patch p, MonadHold t m, MonadFix m) => (PatchTarget p -> b -> PushM t (p, c)) -> PatchTarget p -> Event t b -> m (Incremental t p, Event t c)
387+mapAccumMIncremental f = mapAccumMaybeMIncremental $ \v o -> bimap Just Just <$> f v o
388+mapAccumMaybeIncremental :: (Reflex t, Patch p, MonadHold t m, MonadFix m) => (PatchTarget p -> b -> (Maybe p, Maybe c)) -> PatchTarget p -> Event t b -> m (Incremental t p, Event t c)
389+mapAccumMaybeIncremental f = mapAccumMaybeMIncremental $ \v o -> return $ f v o
390+mapAccumMaybeMIncremental :: (Reflex t, Patch p, MonadHold t m, MonadFix m) => (PatchTarget p -> b -> PushM t (Maybe p, Maybe c)) -> PatchTarget p -> Event t b -> m (Incremental t p, Event t c)
391+mapAccumMaybeMIncremental f z e = do
392+ rec let e' = flip push e $ \o -> do
393+ v <- sample $ currentIncremental d'
395+ return $ case result of
396+ (Nothing, Nothing) -> Nothing
398+ d' <- holdIncremental z $ mapMaybe fst e'
399+ return (d', mapMaybe snd e')
476slowHeadE :: (Reflex t, MonadHold t m, MonadFix m) => Event t a -> m (Event t a)
401slowHeadE :: (Reflex t, MonadHold t m, MonadFix m) => Event t a -> m (Event t a)
477slowHeadE e = do
402slowHeadE e = do
@@ -481,14 +406,14 @@ slowHeadE e = do
482-- | An 'EventSelector' allows you to efficiently 'select' an 'Event' based on a
407-- | An 'EventSelector' allows you to efficiently 'select' an 'Event' based on a
483-- key. This is much more efficient than filtering for each key with
408-- key. This is much more efficient than filtering for each key with
484−-- 'fmapMaybe'.
409+-- 'mapMaybe'.
485newtype EventSelector t k = EventSelector
410newtype EventSelector t k = EventSelector
486 { -- | Retrieve the 'Event' for the given key. The type of the 'Event' is
411 { -- | Retrieve the 'Event' for the given key. The type of the 'Event' is
487 -- determined by the type of the key, so this can be used to fan-out
412 -- determined by the type of the key, so this can be used to fan-out
488 -- 'Event's whose sub-'Event's have different types.
413 -- 'Event's whose sub-'Event's have different types.
490 -- Using 'EventSelector's and the 'fan' primitive is far more efficient than
415 -- Using 'EventSelector's and the 'fan' primitive is far more efficient than
491− -- (but equivalent to) using 'fmapMaybe' to select only the relevant
416+ -- (but equivalent to) using 'mapMaybe' to select only the relevant
492 -- occurrences of an 'Event'.
417 -- occurrences of an 'Event'.
493 select :: forall a. k a -> Event t a
418 select :: forall a. k a -> Event t a
@@ -572,6 +497,14 @@ pushAlways f = push (fmap Just . f)
572ffor :: Functor f => f a -> (a -> b) -> f b
497ffor :: Functor f => f a -> (a -> b) -> f b
573ffor = flip fmap
498ffor = flip fmap
500+-- | Rotated version of 'liftA2'.
501+ffor2 :: Applicative f => f a -> f b -> (a -> b -> c) -> f c
502+ffor2 a b f = liftA2 f a b
504+-- | Rotated version of 'liftA3'.
505+ffor3 :: Applicative f => f a -> f b -> f c -> (a -> b -> c -> d) -> f d
506+ffor3 a b c f = liftA3 f a b c
575instance Reflex t => Applicative (Behavior t) where
508instance Reflex t => Applicative (Behavior t) where
576 pure = constant
509 pure = constant
577 f <*> x = pull $ sample f `ap` sample x
510 f <*> x = pull $ sample f `ap` sample x
@@ -615,6 +548,15 @@ instance (Reflex t, Num a) => Num (Behavior t a) where
615 negate = fmap negate
548 negate = fmap negate
616 signum = fmap signum
549 signum = fmap signum
551+instance (Num a, Reflex t) => Num (Dynamic t a) where
555+ signum = fmap signum
556+ fromInteger = pure . fromInteger
557+ negate = fmap negate
618instance (Reflex t, Semigroup a) => Semigroup (Behavior t a) where
560instance (Reflex t, Semigroup a) => Semigroup (Behavior t a) where
619 a <> b = pull $ liftM2 (<>) (sample a) (sample b)
561 a <> b = pull $ liftM2 (<>) (sample a) (sample b)
620 sconcat = pull . fmap sconcat . mapM sample
562 sconcat = pull . fmap sconcat . mapM sample
@@ -624,22 +566,25 @@ instance (Reflex t, Semigroup a) => Semigroup (Behavior t a) where
624 times1p n = fmap $ times1p n
566 times1p n = fmap $ times1p n
569+-- | Alias for 'mapMaybe'
570+fmapMaybe :: Filterable f => (a -> Maybe b) -> f a -> f b
627−-- | Flipped version of 'fmapMaybe'.
573+-- | Flipped version of 'mapMaybe'.
628−fforMaybe :: FunctorMaybe f => f a -> (a -> Maybe b) -> f b
574+fforMaybe :: Filterable f => f a -> (a -> Maybe b) -> f b
629−fforMaybe = flip fmapMaybe
575+fforMaybe = flip mapMaybe
631-- | Filter 'f a' using the provided predicate.
577-- | Filter 'f a' using the provided predicate.
632−-- Relies on 'fforMaybe'.
633−ffilter :: FunctorMaybe f => (a -> Bool) -> f a -> f a
578+ffilter :: Filterable f => (a -> Bool) -> f a -> f a
634−ffilter f = fmapMaybe $ \x -> if f x then Just x else Nothing
579+ffilter = W.filter
636-- | Filter 'Left's from 'f (Either a b)' into 'a'.
581-- | Filter 'Left's from 'f (Either a b)' into 'a'.
637−filterLeft :: FunctorMaybe f => f (Either a b) -> f a
582+filterLeft :: Filterable f => f (Either a b) -> f a
638−filterLeft = fmapMaybe (either Just (const Nothing))
583+filterLeft = mapMaybe (either Just (const Nothing))
640-- | Filter 'Right's from 'f (Either a b)' into 'b'.
585-- | Filter 'Right's from 'f (Either a b)' into 'b'.
641−filterRight :: FunctorMaybe f => f (Either a b) -> f b
586+filterRight :: Filterable f => f (Either a b) -> f b
642−filterRight = fmapMaybe (either (const Nothing) Just)
587+filterRight = mapMaybe (either (const Nothing) Just)
644-- | Left-biased event union (prefers left event on simultaneous
589-- | Left-biased event union (prefers left event on simultaneous
645-- occurrence).
590-- occurrence).
@@ -657,13 +602,18 @@ instance Reflex t => Bind (Event t) where
658instance Reflex t => Functor (Event t) where
603instance Reflex t => Functor (Event t) where
659 {-# INLINE fmap #-}
604 {-# INLINE fmap #-}
660− fmap f = fmapMaybe $ Just . f
605+ fmap f = mapMaybe $ Just . f
661 {-# INLINE (<$) #-}
606 {-# INLINE (<$) #-}
662 x <$ e = fmapCheap (const x) e
607 x <$ e = fmapCheap (const x) e
609+-- TODO Remove this instance
664instance Reflex t => FunctorMaybe (Event t) where
610instance Reflex t => FunctorMaybe (Event t) where
665 {-# INLINE fmapMaybe #-}
611 {-# INLINE fmapMaybe #-}
612+ fmapMaybe = mapMaybe
614+instance Reflex t => Filterable (Event t) where
615+ {-# INLINE mapMaybe #-}
666− fmapMaybe f = push $ return . f
616+ mapMaybe f = push $ return . f
668-- | Never: @'zero' = 'never'@.
618-- | Never: @'zero' = 'never'@.
669instance Reflex t => Plus (Event t) where
619instance Reflex t => Plus (Event t) where
@@ -674,7 +624,13 @@ instance Reflex t => Plus (Event t) where
674tag :: Reflex t => Behavior t b -> Event t a -> Event t b
624tag :: Reflex t => Behavior t b -> Event t a -> Event t b
675tag b = pushAlways $ \_ -> sample b
625tag b = pushAlways $ \_ -> sample b
627+-- | Replace each occurrence value of the 'Event' with the value of the
628+-- 'Behavior' at that time; if it is 'Just', fire with the contained value; if
629+-- it is 'Nothing', drop the occurrence.
630+tagMaybe :: Reflex t => Behavior t (Maybe b) -> Event t a -> Event t b
631+tagMaybe b = push $ \_ -> sample b
677−-- | Create a new 'Event' that combines occurences of supplied 'Event' with the
633+-- | Create a new 'Event' that combines occurrences of supplied 'Event' with the
678-- current value of the 'Behavior'.
634-- current value of the 'Behavior'.
679attach :: Reflex t => Behavior t a -> Event t b -> Event t (a, b)
635attach :: Reflex t => Behavior t a -> Event t b -> Event t (a, b)
680attach = attachWith (,)
636attach = attachWith (,)
@@ -684,53 +640,118 @@ attach = attachWith (,)
684attachWith :: Reflex t => (a -> b -> c) -> Behavior t a -> Event t b -> Event t c
640attachWith :: Reflex t => (a -> b -> c) -> Behavior t a -> Event t b -> Event t c
685attachWith f = attachWithMaybe $ \a b -> Just $ f a b
641attachWith f = attachWithMaybe $ \a b -> Just $ f a b
687−-- | Create a new 'Event' by combining each occurence with the current value of
643+-- | Create a new 'Event' by combining each occurrence with the current value of
688-- the 'Behavior'. The occurrence is discarded if the combining function returns
644-- the 'Behavior'. The occurrence is discarded if the combining function returns
689-- Nothing
645-- Nothing
690attachWithMaybe :: Reflex t => (a -> b -> Maybe c) -> Behavior t a -> Event t b -> Event t c
646attachWithMaybe :: Reflex t => (a -> b -> Maybe c) -> Behavior t a -> Event t b -> Event t c
691attachWithMaybe f b e = flip push e $ \o -> (`f` o) <$> sample b
647attachWithMaybe f b e = flip push e $ \o -> (`f` o) <$> sample b
693−-- | Create a new 'Event' that occurs on all but the first occurence of the
649+-- | Create a new 'Event' that occurs on all but the first occurrence of the
694-- supplied 'Event'.
650-- supplied 'Event'.
695−tailE :: (Reflex t, MonadHold t m, MonadFix m) => Event t a -> m (Event t a)
651+tailE :: (Reflex t, MonadHold t m) => Event t a -> m (Event t a)
696tailE e = snd <$> headTailE e
652tailE e = snd <$> headTailE e
698−-- | Create a tuple of two 'Event's with the first one occuring only the first
654+-- | Create a tuple of two 'Event's with the first one occurring only the first
699−-- time the supplied 'Event' occurs and the second occuring on all but the first
655+-- time the supplied 'Event' occurs and the second occurring on all but the first
700−-- occurence.
656+-- occurrence.
701−headTailE :: (Reflex t, MonadHold t m, MonadFix m) => Event t a -> m (Event t a, Event t a)
657+headTailE :: (Reflex t, MonadHold t m) => Event t a -> m (Event t a, Event t a)
702headTailE e = do
658headTailE e = do
703 eHead <- headE e
659 eHead <- headE e
704 be <- hold never $ fmap (const e) eHead
660 be <- hold never $ fmap (const e) eHead
705 return (eHead, switch be)
661 return (eHead, switch be)
663+-- | Take the streak of occurrences starting at the current time for which the
664+-- event returns 'True'.
707−-- | Starting at the current time, fire all the occurrences of the 'Event' for
666+-- Starting at the current time, fire all the occurrences of the 'Event' for
708−-- which the given predicate returns 'True'. When 'False' is returned, do not
667+-- which the given predicate returns 'True'. When first 'False' is returned,
709−-- fire, and permanently stop firing, even if 'True' values are encountered
668+-- do not fire, and permanently stop firing, even if 'True' values would have
710−-- later.
669+-- been encountered later.
711−takeWhileE :: forall t m a. (Reflex t, MonadFix m, MonadHold t m) => (a -> Bool) -> Event t a -> m (Event t a)
672+ . (Reflex t, MonadFix m, MonadHold t m)
712−takeWhileE f e = do
673+ => (a -> Bool)
676+takeWhileE f = takeWhileJustE $ \v -> guard (f v) $> v
678+-- | Take the streak of occurrences starting at the current time for which the
679+-- event returns 'Just b'.
681+-- Starting at the current time, fire all the occurrences of the 'Event' for
682+-- which the given predicate returns 'Just b'. When first 'Nothing' is returned,
683+-- do not fire, and permanently stop firing, even if 'Just b' values would have
684+-- been encountered later.
687+ . (Reflex t, MonadFix m, MonadHold t m)
691+takeWhileJustE f e = do
713− rec let (eFalse, eTrue) = fanEither $ ffor e' $ \a -> if f a
692+ rec let (eBad, eTrue) = fanEither $ ffor e' $ \a -> case f a of
715− else Left never
693+ Nothing -> Left never
716− be <- hold e eFalse
694+ Just b -> Right b
717− let e' = switch be
695+ eFirstBad <- headE eBad
696+ e' <- switchHold e eFirstBad
718 return eTrue
697 return eTrue
699+-- | Drop the streak of occurrences starting at the current time for which the
700+-- event returns 'True'.
702+-- Starting at the current time, do not fire all the occurrences of the 'Event'
703+-- for which the given predicate returns 'True'. When 'False' is first
704+-- returned, do fire, and permanently continue firing, even if 'True' values
705+-- would have been encountered later.
708+ . (Reflex t, MonadFix m, MonadHold t m)
712+dropWhileE f e = snd <$> takeDropWhileJustE (\v -> guard (f v) $> v) e
714+-- | Both take and drop the streak of occurrences starting at the current time
715+-- for which the event returns 'Just b'.
717+-- For the left event, starting at the current time, fire all the occurrences
718+-- of the 'Event' for which the given function returns 'Just b'. When
719+-- 'Nothing' is returned, do not fire, and permanently stop firing, even if
720+-- 'Just b' values would have been encountered later.
722+-- For the right event, do not fire until the first occurrence where the given
723+-- function returns 'Nothing', and fire that one and all subsequent
724+-- occurrences. Even if the function would have again returned 'Just b', keep
728+ . (Reflex t, MonadFix m, MonadHold t m)
731+ -> m (Event t b, Event t a)
732+takeDropWhileJustE f e = do
733+ rec let (eBad, eGood) = fanEither $ ffor e' $ \a -> case f a of
736+ eFirstBad <- headE eBad
737+ e' <- switchHold e (never <$ eFirstBad)
738+ eRest <- switchHoldPromptOnly never (e <$ eFirstBad)
739+ return (eGood, eRest)
720−-- | Split the supplied 'Event' into two individual 'Event's occuring at the
741+-- | Split the supplied 'Event' into two individual 'Event's occurring at the
721-- same time with the respective values from the tuple.
742-- same time with the respective values from the tuple.
722splitE :: Reflex t => Event t (a, b) -> (Event t a, Event t b)
743splitE :: Reflex t => Event t (a, b) -> (Event t a, Event t b)
723splitE e = (fmap fst e, fmap snd e)
744splitE e = (fmap fst e, fmap snd e)
725-- | Print the supplied 'String' and the value of the 'Event' on each
746-- | Print the supplied 'String' and the value of the 'Event' on each
726−-- occurence. This should /only/ be used for debugging.
747+-- occurrence. This should /only/ be used for debugging.
728-- Note: As with Debug.Trace.trace, the message will only be printed if the
749-- Note: As with Debug.Trace.trace, the message will only be printed if the
729-- 'Event' is actually used.
750-- 'Event' is actually used.
730traceEvent :: (Reflex t, Show a) => String -> Event t a -> Event t a
751traceEvent :: (Reflex t, Show a) => String -> Event t a -> Event t a
731traceEvent s = traceEventWith $ \x -> s <> ": " <> show x
752traceEvent s = traceEventWith $ \x -> s <> ": " <> show x
733−-- | Print the output of the supplied function on each occurence of the
754+-- | Print the output of the supplied function on each occurrence of the
734-- 'Event'. This should /only/ be used for debugging.
755-- 'Event'. This should /only/ be used for debugging.
736-- Note: As with Debug.Trace.trace, the message will only be printed if the
757-- Note: As with Debug.Trace.trace, the message will only be printed if the
@@ -774,7 +795,7 @@ leftmost :: Reflex t => [Event t a] -> Event t a
774leftmost = mergeWith const
795leftmost = mergeWith const
776-- | Create a new 'Event' that occurs if at least one of the 'Event's in the
797-- | Create a new 'Event' that occurs if at least one of the 'Event's in the
777−-- list occurs and has a list of the values of all 'Event's occuring at that
798+-- list occurs and has a list of the values of all 'Event's occurring at that
779mergeList :: Reflex t => [Event t a] -> Event t (NonEmpty a)
800mergeList :: Reflex t => [Event t a] -> Event t (NonEmpty a)
780mergeList [] = never
801mergeList [] = never
@@ -785,10 +806,14 @@ unsafeMapIncremental f g a = unsafeBuildIncremental (fmap f $ sample $ currentIn
786-- | Create a new 'Event' combining the map of 'Event's into an 'Event' that
807-- | Create a new 'Event' combining the map of 'Event's into an 'Event' that
787-- occurs if at least one of them occurs and has a map of values of all 'Event's
808-- occurs if at least one of them occurs and has a map of values of all 'Event's
788−-- occuring at that time.
809+-- occurring at that time.
789mergeMap :: (Reflex t, Ord k) => Map k (Event t a) -> Event t (Map k a)
810mergeMap :: (Reflex t, Ord k) => Map k (Event t a) -> Event t (Map k a)
790mergeMap = fmap dmapToMap . merge . mapWithFunctorToDMap
811mergeMap = fmap dmapToMap . merge . mapWithFunctorToDMap
813+-- | Like 'mergeMap' but for 'IntMap'.
814+mergeIntMap :: Reflex t => IntMap (Event t a) -> Event t (IntMap a)
815+mergeIntMap = fmap dmapToIntMap . merge . intMapWithFunctorToDMap
792-- | Create a merge whose parents can change over time
817-- | Create a merge whose parents can change over time
793mergeMapIncremental :: (Reflex t, Ord k) => Incremental t (PatchMap k (Event t a)) -> Event t (Map k a)
818mergeMapIncremental :: (Reflex t, Ord k) => Incremental t (PatchMap k (Event t a)) -> Event t (Map k a)
794mergeMapIncremental = fmap dmapToMap . mergeIncremental . unsafeMapIncremental mapWithFunctorToDMap (const2PatchDMapWith id)
819mergeMapIncremental = fmap dmapToMap . mergeIncremental . unsafeMapIncremental mapWithFunctorToDMap (const2PatchDMapWith id)
@@ -806,7 +831,7 @@ fanEither :: Reflex t => Event t (Either a b) -> (Event t a, Event t b)
806fanEither e =
831fanEither e =
807 let justLeft = either Just (const Nothing)
832 let justLeft = either Just (const Nothing)
808 justRight = either (const Nothing) Just
833 justRight = either (const Nothing) Just
809− in (fmapMaybe justLeft e, fmapMaybe justRight e)
834+ in (mapMaybe justLeft e, mapMaybe justRight e)
811-- | Split the event into separate events for 'This' and 'That' values,
836-- | Split the event into separate events for 'This' and 'That' values,
812-- allowing them to fire simultaneously when the input value is 'These'.
837-- allowing them to fire simultaneously when the input value is 'These'.
@@ -818,43 +843,114 @@ fanThese e =
818 that (That y) = Just y
843 that (That y) = Just y
819 that (These _ y) = Just y
844 that (These _ y) = Just y
820 that _ = Nothing
845 that _ = Nothing
821− in (fmapMaybe this e, fmapMaybe that e)
846+ in (mapMaybe this e, mapMaybe that e)
823-- | Split the event into an 'EventSelector' that allows efficient selection of
848-- | Split the event into an 'EventSelector' that allows efficient selection of
824-- the individual 'Event's.
849-- the individual 'Event's.
825fanMap :: (Reflex t, Ord k) => Event t (Map k a) -> EventSelector t (Const2 k a)
850fanMap :: (Reflex t, Ord k) => Event t (Map k a) -> EventSelector t (Const2 k a)
826fanMap = fan . fmap mapToDMap
851fanMap = fan . fmap mapToDMap
828−-- | Switches to the new event whenever it receives one. Whenever a new event
853+-- | Switches to the new event whenever it receives one. Only the old event is
854+-- considered the moment a new one is switched in; the output event will fire at
855+-- that moment only if the old event does.
857+-- Because the simultaneous firing case is irrelevant, this function imposes
858+-- laxer "timing requirements" on the overall circuit, avoiding many potential
859+-- cyclic dependency / metastability failures. It's also more performant. Use
860+-- this rather than 'switchHoldPromptly' and 'switchHoldPromptOnly' unless you
861+-- are absolutely sure you need to act on the new event in the coincidental
863+switchHold :: (Reflex t, MonadHold t m) => Event t a -> Event t (Event t a) -> m (Event t a)
864+switchHold ea0 eea = switch <$> hold ea0 eea
866+-- | Switches to the new event whenever it receives one. Whenever a new event is
829−-- is provided, if it is firing, its value will be the resulting event's value;
867+-- provided, if it is firing, its value will be the resulting event's value; if
830−-- if it is not firing, but the old one is, the old one's value will be used.
868+-- it is not firing, but the old one is, the old one's value will be used.
870+-- 'switchHold', by always forwarding the old event the moment it is switched
871+-- out, avoids many potential cyclic dependency problems / metastability
872+-- problems. It's also more performant. Use it instead unless you are sure you
831−switchPromptly :: (Reflex t, MonadHold t m) => Event t a -> Event t (Event t a) -> m (Event t a)
874+switchHoldPromptly :: (Reflex t, MonadHold t m) => Event t a -> Event t (Event t a) -> m (Event t a)
832−switchPromptly ea0 eea = do
875+switchHoldPromptly ea0 eea = do
833 bea <- hold ea0 eea
876 bea <- hold ea0 eea
834 let eLag = switch bea
877 let eLag = switch bea
835 eCoincidences = coincidence eea
878 eCoincidences = coincidence eea
836 return $ leftmost [eCoincidences, eLag]
879 return $ leftmost [eCoincidences, eLag]
838−-- | 'switch'es to a new event whenever it receives one. At the moment of
881+-- | switches to a new event whenever it receives one. At the moment of
839-- switching, the old event will be ignored if it fires, and the new one will be
882-- switching, the old event will be ignored if it fires, and the new one will be
840-- used if it fires; this is the opposite of 'switch', which will use only the
883-- used if it fires; this is the opposite of 'switch', which will use only the
841-- old value.
884-- old value.
886+-- 'switchHold', by always forwarding the old event the moment it is switched
887+-- out, avoids many potential cyclic dependency problems / metastability
888+-- problems. It's also more performant. Use it instead unless you are sure you
842−switchPromptOnly :: (Reflex t, MonadHold t m) => Event t a -> Event t (Event t a) -> m (Event t a)
890+switchHoldPromptOnly :: (Reflex t, MonadHold t m) => Event t a -> Event t (Event t a) -> m (Event t a)
843−switchPromptOnly e0 e' = do
891+switchHoldPromptOnly e0 e' = do
844 eLag <- switch <$> hold e0 e'
892 eLag <- switch <$> hold e0 e'
845 return $ coincidence $ leftmost [e', eLag <$ eLag]
893 return $ coincidence $ leftmost [e', eLag <$ eLag]
895+-- | When the given outer event fires, condense the inner events into the contained patch. Non-firing inner events will be replaced with deletions.
896+coincidencePatchMap :: (Reflex t, Ord k) => Event t (PatchMap k (Event t v)) -> Event t (PatchMap k v)
897+coincidencePatchMap e = fmapCheap PatchMap $ coincidence $ ffor e $ \(PatchMap m) -> mergeMap $ ffor m $ \case
898+ Nothing -> fmapCheap (const Nothing) e
899+ Just ev -> leftmost [fmapCheap Just ev, fmapCheap (const Nothing) e]
901+-- | See 'coincidencePatchMap'
902+coincidencePatchIntMap :: Reflex t => Event t (PatchIntMap (Event t v)) -> Event t (PatchIntMap v)
903+coincidencePatchIntMap e = fmapCheap PatchIntMap $ coincidence $ ffor e $ \(PatchIntMap m) -> mergeIntMap $ ffor m $ \case
904+ Nothing -> fmapCheap (const Nothing) e
905+ Just ev -> leftmost [fmapCheap Just ev, fmapCheap (const Nothing) e]
907+-- | See 'coincidencePatchMap'
908+coincidencePatchMapWithMove :: (Reflex t, Ord k) => Event t (PatchMapWithMove k (Event t v)) -> Event t (PatchMapWithMove k v)
909+coincidencePatchMapWithMove e = fmapCheap unsafePatchMapWithMove $ coincidence $ ffor e $ \p -> mergeMap $ ffor (unPatchMapWithMove p) $ \ni -> case PatchMapWithMove._nodeInfo_from ni of
910+ PatchMapWithMove.From_Delete -> fforCheap e $ \_ ->
911+ ni { PatchMapWithMove._nodeInfo_from = PatchMapWithMove.From_Delete }
912+ PatchMapWithMove.From_Move k -> fforCheap e $ \_ ->
913+ ni { PatchMapWithMove._nodeInfo_from = PatchMapWithMove.From_Move k }
914+ PatchMapWithMove.From_Insert ev -> leftmost
915+ [ fforCheap ev $ \v ->
916+ ni { PatchMapWithMove._nodeInfo_from = PatchMapWithMove.From_Insert v }
917+ , fforCheap e $ \_ ->
918+ ni { PatchMapWithMove._nodeInfo_from = PatchMapWithMove.From_Delete }
921+switchHoldPromptOnlyIncremental
922+ :: forall t m p pt w
925+ , Patch (p (Event t w))
926+ , PatchTarget (p (Event t w)) ~ pt (Event t w)
928+ , PatchTarget (p w) ~ pt w
931+ => (Incremental t (p (Event t w)) -> Event t (pt w))
932+ -> (Event t (p (Event t w)) -> Event t (p w))
934+ -> Event t (p (Event t w))
935+ -> m (Event t (pt w))
936+switchHoldPromptOnlyIncremental mergePatchIncremental coincidencePatch e0 e' = do
937+ lag <- mergePatchIncremental <$> holdIncremental e0 e'
938+ pure $ ffor (align lag (coincidencePatch e')) $ \case
940+ That new -> new `applyAlways` mempty
941+ These old new -> new `applyAlways` old
847instance Reflex t => Align (Event t) where
943instance Reflex t => Align (Event t) where
848 nil = never
944 nil = never
849 align = alignEventWithMaybe Just
945 align = alignEventWithMaybe Just
851-- | Create a new 'Event' that only occurs if the supplied 'Event' occurs and
947-- | Create a new 'Event' that only occurs if the supplied 'Event' occurs and
852−-- the 'Behavior' is true at the time of occurence.
948+-- the 'Behavior' is true at the time of occurrence.
853gate :: Reflex t => Behavior t Bool -> Event t a -> Event t a
949gate :: Reflex t => Behavior t Bool -> Event t a -> Event t a
854gate = attachWithMaybe $ \allow a -> if allow then Just a else Nothing
950gate = attachWithMaybe $ \allow a -> if allow then Just a else Nothing
856−-- | Create a new behavior given a starting behavior and switch to a the behvior
952+-- | Create a new behavior given a starting behavior and switch to the behavior
857−-- carried by the event when it fires.
953+-- carried by the event when it fires.
858switcher :: (Reflex t, MonadHold t m)
954switcher :: (Reflex t, MonadHold t m)
859 => Behavior t a -> Event t (Behavior t a) -> m (Behavior t a)
955 => Behavior t a -> Event t (Behavior t a) -> m (Behavior t a)
860switcher b eb = pull . (sample <=< sample) <$> hold b eb
956switcher b eb = pull . (sample <=< sample) <$> hold b eb
@@ -869,7 +965,7 @@ zipDyn = zipDynWith (,)
870-- | Combine two 'Dynamic's with a combining function. The result will change
966-- | Combine two 'Dynamic's with a combining function. The result will change
871-- whenever either (or both) input 'Dynamic' changes.
967-- whenever either (or both) input 'Dynamic' changes.
872−-- More efficient than liftA2.
968+-- More efficient than 'liftA2'.
873zipDynWith :: Reflex t => (a -> b -> c) -> Dynamic t a -> Dynamic t b -> Dynamic t c
969zipDynWith :: Reflex t => (a -> b -> c) -> Dynamic t a -> Dynamic t b -> Dynamic t c
874zipDynWith f da db =
970zipDynWith f da db =
875 let eab = align (updated da) (updated db)
971 let eab = align (updated da) (updated db)
@@ -885,6 +981,14 @@ zipDynWith f da db =
885 return $ Just $ f a b
981 return $ Just $ f a b
886 in unsafeBuildDynamic (f <$> sample (current da) <*> sample (current db)) ec
982 in unsafeBuildDynamic (f <$> sample (current da) <*> sample (current db)) ec
984+instance (Reflex t, Semigroup a) => Semigroup (Dynamic t a) where
985+ (<>) = zipDynWith (<>)
986+#if MIN_VERSION_semigroups(0,17,0)
987+ stimes n = fmap $ stimes n
989+ times1p n = fmap $ times1p n
888instance (Reflex t, Monoid a) => Monoid (Dynamic t a) where
992instance (Reflex t, Monoid a) => Monoid (Dynamic t a) where
889 mconcat = distributeListOverDynWith mconcat
993 mconcat = distributeListOverDynWith mconcat
890 mempty = constDyn mempty
994 mempty = constDyn mempty
@@ -892,7 +996,7 @@ instance (Reflex t, Monoid a) => Monoid (Dynamic t a) where
893-- | This function converts a 'DMap' whose elements are 'Dynamic's into a
997-- | This function converts a 'DMap' whose elements are 'Dynamic's into a
894-- 'Dynamic' 'DMap'. Its implementation is more efficient than doing the same
998-- 'Dynamic' 'DMap'. Its implementation is more efficient than doing the same
895−-- through the use of multiple uses of 'zipWithDyn' or 'Applicative' operators.
999+-- through the use of multiple uses of 'zipDynWith' or 'Applicative' operators.
896distributeDMapOverDynPure :: forall t k. (Reflex t, GCompare k) => DMap k (Dynamic t) -> Dynamic t (DMap k Identity)
1000distributeDMapOverDynPure :: forall t k. (Reflex t, GCompare k) => DMap k (Dynamic t) -> Dynamic t (DMap k Identity)
897distributeDMapOverDynPure dm = case DMap.toList dm of
1001distributeDMapOverDynPure dm = case DMap.toList dm of
898 [] -> constDyn DMap.empty
1002 [] -> constDyn DMap.empty
@@ -918,14 +1022,57 @@ distributeListOverDynWith f = fmap (f . map (\(Const2 _ :=> Identity v) -> v) .
918difference :: Reflex t => Event t a -> Event t b -> Event t a
1022difference :: Reflex t => Event t a -> Event t b -> Event t a
919difference = alignEventWithMaybe $ \case
1023difference = alignEventWithMaybe $ \case
920 This a -> Just a
1024 This a -> Just a
921− _ -> Nothing
1025+ _ -> Nothing
1027+-- | Zips two values by taking the union of their shapes and combining with the provided function.
1028+-- 'Nothing' values are dropped.
923alignEventWithMaybe :: Reflex t => (These a b -> Maybe c) -> Event t a -> Event t b -> Event t c
1029alignEventWithMaybe :: Reflex t => (These a b -> Maybe c) -> Event t a -> Event t b -> Event t c
924−alignEventWithMaybe f ea eb =
1030+alignEventWithMaybe f ea eb = mapMaybe (f <=< dmapToThese) $
925− fmapMaybe (f <=< dmapToThese)
927− $ DMap.fromList [LeftTag :=> ea, RightTag :=> eb]
1031+ merge $ DMap.fromList [LeftTag :=> ea, RightTag :=> eb]
1033+-- | Produces an 'Event' that fires only when the input event fires with a 'DSum' key that
1034+-- matches the provided key.
1036+ :: forall t m k v a.
1043+ -> Event t (DSum k v)
1044+ -> m (Event t (v a))
1045+filterEventKey k kv' = do
1046+ let f :: DSum k v -> Maybe (v a)
1047+ f (newK :=> newV) = case newK `geq` k of
1048+ Just Refl -> Just newV
1050+ takeWhileJustE f kv'
1052+-- | "Factor" the input 'DSum' 'Event' to produce an 'Event' which
1053+-- fires when the 'DSum' key changes and contains both the value of the
1054+-- 'DSum' at switchover and an 'Event' of values produced by subsequent
1055+-- firings of the input 'Event' that do not change the 'DSum' key.
1057+ :: forall t m k v a.
1064+ -> Event t (DSum k v)
1065+ -> m (Event t (v a), Event t (DSum k (Product v (Compose (Event t) v))))
1066+factorEvent k0 kv' = do
1067+ key :: Behavior t (Some k) <- hold (Some.This k0) $ fmapCheap (\(k :=> _) -> Some.This k) kv'
1068+ let update = flip push kv' $ \(newKey :=> newVal) -> sample key >>= \case
1069+ Some.This oldKey -> case newKey `geq` oldKey of
1070+ Just Refl -> return Nothing
1072+ newInner <- filterEventKey newKey kv'
1073+ return $ Just $ newKey :=> Pair newVal (Compose newInner)
1074+ eInitial <- filterEventKey k0 kv'
1075+ return (eInitial, update)
930--------------------------------------------------------------------------------
1077--------------------------------------------------------------------------------
931-- Accumulator
1078-- Accumulator
@@ -955,26 +1102,94 @@ class Reflex t => Accumulator t f | f -> t where
955 mapAccumMaybe f = mapAccumMaybeM $ \v o -> return $ f v o
1102 mapAccumMaybe f = mapAccumMaybeM $ \v o -> return $ f v o
956 mapAccumMaybeM :: (MonadHold t m, MonadFix m) => (a -> b -> PushM t (Maybe a, Maybe c)) -> a -> Event t b -> m (f a, Event t c)
1103 mapAccumMaybeM :: (MonadHold t m, MonadFix m) => (a -> b -> PushM t (Maybe a, Maybe c)) -> a -> Event t b -> m (f a, Event t c)
1105+-- | Accumulate a 'Dynamic' by folding occurrences of an 'Event'
1106+-- with the provided function. See 'foldDyn'.
958−accumDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> a) -> a -> Event t b -> m (Dynamic t a)
1108+ :: (Reflex t, MonadHold t m, MonadFix m)
959accumDyn f = accumMaybeDyn $ \v o -> Just $ f v o
1113accumDyn f = accumMaybeDyn $ \v o -> Just $ f v o
1115+-- | Accumulate a 'Dynamic' by folding occurrences of an 'Event'
1116+-- with the provided 'PushM' action.
960−accumMDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t a) -> a -> Event t b -> m (Dynamic t a)
1118+ :: (Reflex t, MonadHold t m, MonadFix m)
1119+ => (a -> b -> PushM t a)
961accumMDyn f = accumMaybeMDyn $ \v o -> Just <$> f v o
1123accumMDyn f = accumMaybeMDyn $ \v o -> Just <$> f v o
1125+-- | Accumulate a 'Dynamic' by folding occurrences of an 'Event'
1126+-- with the provided function, discarding 'Nothing' results.
962−accumMaybeDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> Maybe a) -> a -> Event t b -> m (Dynamic t a)
1128+ :: (Reflex t, MonadHold t m, MonadFix m)
1129+ => (a -> b -> Maybe a)
963accumMaybeDyn f = accumMaybeMDyn $ \v o -> return $ f v o
1133accumMaybeDyn f = accumMaybeMDyn $ \v o -> return $ f v o
1135+-- | Accumulate a 'Dynamic' by folding occurrences of an 'Event'
1136+-- with the provided 'PushM' action, discarding 'Nothing' results.
964−accumMaybeMDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t (Maybe a)) -> a -> Event t b -> m (Dynamic t a)
1138+ :: (Reflex t, MonadHold t m, MonadFix m)
1139+ => (a -> b -> PushM t (Maybe a))
965accumMaybeMDyn f z e = do
1143accumMaybeMDyn f z e = do
966 rec let e' = flip push e $ \o -> do
1144 rec let e' = flip push e $ \o -> do
967 v <- sample $ current d'
1145 v <- sample $ current d'
969 d' <- holdDyn z e'
1147 d' <- holdDyn z e'
970 return d'
1148 return d'
1150+-- | Accumulate a 'Dynamic' by folding occurrences of an 'Event'
1151+-- with a function that both accumulates and produces a value to fire
1152+-- as an 'Event'. Returns both the accumulated value and an 'Event'.
971−mapAccumDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> (a, c)) -> a -> Event t b -> m (Dynamic t a, Event t c)
1154+ :: (Reflex t, MonadHold t m, MonadFix m)
1155+ => (a -> b -> (a, c))
1158+ -> m (Dynamic t a, Event t c)
972mapAccumDyn f = mapAccumMaybeDyn $ \v o -> bimap Just Just $ f v o
1159mapAccumDyn f = mapAccumMaybeDyn $ \v o -> bimap Just Just $ f v o
1161+-- | Similar to 'mapAccumDyn' except that the combining function is a
973−mapAccumMDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t (a, c)) -> a -> Event t b -> m (Dynamic t a, Event t c)
1164+ :: (Reflex t, MonadHold t m, MonadFix m)
1165+ => (a -> b -> PushM t (a, c))
1168+ -> m (Dynamic t a, Event t c)
974mapAccumMDyn f = mapAccumMaybeMDyn $ \v o -> bimap Just Just <$> f v o
1169mapAccumMDyn f = mapAccumMaybeMDyn $ \v o -> bimap Just Just <$> f v o
1171+-- | Accumulate a 'Dynamic' by folding occurrences of an 'Event' with
1172+-- a function that both optionally accumulates and optionally produces
1173+-- a value to fire as a separate output 'Event'.
1174+-- Note that because 'Nothing's are discarded in both cases, the output
1175+-- 'Event' may fire even though the output 'Dynamic' has not changed, and
1176+-- the output 'Dynamic' may update even when the output 'Event' is not firing.
975−mapAccumMaybeDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> (Maybe a, Maybe c)) -> a -> Event t b -> m (Dynamic t a, Event t c)
1178+ :: (Reflex t, MonadHold t m, MonadFix m)
1179+ => (a -> b -> (Maybe a, Maybe c))
1182+ -> m (Dynamic t a, Event t c)
976mapAccumMaybeDyn f = mapAccumMaybeMDyn $ \v o -> return $ f v o
1183mapAccumMaybeDyn f = mapAccumMaybeMDyn $ \v o -> return $ f v o
1185+-- | Like 'mapAccumMaybeDyn' except that the combining function is a
977−mapAccumMaybeMDyn :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t (Maybe a, Maybe c)) -> a -> Event t b -> m (Dynamic t a, Event t c)
1188+ :: (Reflex t, MonadHold t m, MonadFix m)
1189+ => (a -> b -> PushM t (Maybe a, Maybe c))
1192+ -> m (Dynamic t a, Event t c)
978mapAccumMaybeMDyn f z e = do
1193mapAccumMaybeMDyn f z e = do
979 rec let e' = flip push e $ \o -> do
1194 rec let e' = flip push e $ \o -> do
980 v <- sample $ current d'
1195 v <- sample $ current d'
@@ -982,18 +1197,42 @@ mapAccumMaybeMDyn f z e = do
982 return $ case result of
1197 return $ case result of
983 (Nothing, Nothing) -> Nothing
1198 (Nothing, Nothing) -> Nothing
984 _ -> Just result
1199 _ -> Just result
985− d' <- holdDyn z $ fmapMaybe fst e'
1200+ d' <- holdDyn z $ mapMaybe fst e'
986− return (d', fmapMaybe snd e')
1201+ return (d', mapMaybe snd e')
1203+-- | Accumulate a 'Behavior' by folding occurrences of an 'Event'
1204+-- with the provided function.
988{-# INLINE accumB #-}
1205{-# INLINE accumB #-}
989−accumB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> a) -> a -> Event t b -> m (Behavior t a)
1207+ :: (Reflex t, MonadHold t m, MonadFix m)
1211+ -> m (Behavior t a)
990accumB f = accumMaybeB $ \v o -> Just $ f v o
1212accumB f = accumMaybeB $ \v o -> Just $ f v o
1214+-- | Like 'accumB' except that the combining function is a 'PushM' action.
991{-# INLINE accumMB #-}
1215{-# INLINE accumMB #-}
992−accumMB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t a) -> a -> Event t b -> m (Behavior t a)
1217+ :: (Reflex t, MonadHold t m, MonadFix m)
1218+ => (a -> b -> PushM t a)
1221+ -> m (Behavior t a)
993accumMB f = accumMaybeMB $ \v o -> Just <$> f v o
1222accumMB f = accumMaybeMB $ \v o -> Just <$> f v o
1224+-- | Accumulate a 'Behavior' by folding occurrences of an 'Event'
1225+-- with the provided function, discarding 'Nothing' results.
994{-# INLINE accumMaybeB #-}
1226{-# INLINE accumMaybeB #-}
995−accumMaybeB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> Maybe a) -> a -> Event t b -> m (Behavior t a)
1228+ :: (Reflex t, MonadHold t m, MonadFix m)
1229+ => (a -> b -> Maybe a)
1232+ -> m (Behavior t a)
996accumMaybeB f = accumMaybeMB $ \v o -> return $ f v o
1233accumMaybeB f = accumMaybeMB $ \v o -> return $ f v o
1235+-- | Like 'accumMaybeB' except that the combining function is a 'PushM' action.
997{-# INLINE accumMaybeMB #-}
1236{-# INLINE accumMaybeMB #-}
998accumMaybeMB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t (Maybe a)) -> a -> Event t b -> m (Behavior t a)
1237accumMaybeMB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t (Maybe a)) -> a -> Event t b -> m (Behavior t a)
999accumMaybeMB f z e = do
1238accumMaybeMB f z e = do
@@ -1002,16 +1241,42 @@ accumMaybeMB f z e = do
1003 d' <- hold z e'
1242 d' <- hold z e'
1004 return d'
1243 return d'
1245+-- | Accumulate a 'Behavior' by folding occurrences of an 'Event'
1246+-- with a function that both accumulates and produces a value to fire
1247+-- as an 'Event'. Returns both the accumulated value and an 'Event'.
1005{-# INLINE mapAccumB #-}
1248{-# INLINE mapAccumB #-}
1006−mapAccumB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> (a, c)) -> a -> Event t b -> m (Behavior t a, Event t c)
1250+ :: (Reflex t, MonadHold t m, MonadFix m)
1251+ => (a -> b -> (a, c))
1254+ -> m (Behavior t a, Event t c)
1007mapAccumB f = mapAccumMaybeB $ \v o -> bimap Just Just $ f v o
1255mapAccumB f = mapAccumMaybeB $ \v o -> bimap Just Just $ f v o
1257+-- | Like 'mapAccumB' except that the combining function is a 'PushM' action.
1008{-# INLINE mapAccumMB #-}
1258{-# INLINE mapAccumMB #-}
1009−mapAccumMB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t (a, c)) -> a -> Event t b -> m (Behavior t a, Event t c)
1260+ :: (Reflex t, MonadHold t m, MonadFix m)
1261+ => (a -> b -> PushM t (a, c))
1264+ -> m (Behavior t a, Event t c)
1010mapAccumMB f = mapAccumMaybeMB $ \v o -> bimap Just Just <$> f v o
1265mapAccumMB f = mapAccumMaybeMB $ \v o -> bimap Just Just <$> f v o
1267+-- | Accumulate a 'Behavior' by folding occurrences of an 'Event' with
1268+-- a function that both optionally accumulates and optionally produces
1269+-- a value to fire as a separate output 'Event'. 'Nothing's are discarded.
1011{-# INLINE mapAccumMaybeB #-}
1270{-# INLINE mapAccumMaybeB #-}
1012−mapAccumMaybeB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> (Maybe a, Maybe c)) -> a -> Event t b -> m (Behavior t a, Event t c)
1272+ :: (Reflex t, MonadHold t m, MonadFix m)
1273+ => (a -> b -> (Maybe a, Maybe c))
1276+ -> m (Behavior t a, Event t c)
1013mapAccumMaybeB f = mapAccumMaybeMB $ \v o -> return $ f v o
1277mapAccumMaybeB f = mapAccumMaybeMB $ \v o -> return $ f v o
1279+-- | LIke 'mapAccumMaybeB' except that the combining function is a 'PushM' action.
1015{-# INLINE mapAccumMaybeMB #-}
1280{-# INLINE mapAccumMaybeMB #-}
1016mapAccumMaybeMB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t (Maybe a, Maybe c)) -> a -> Event t b -> m (Behavior t a, Event t c)
1281mapAccumMaybeMB :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> PushM t (Maybe a, Maybe c)) -> a -> Event t b -> m (Behavior t a, Event t c)
1017mapAccumMaybeMB f z e = do
1282mapAccumMaybeMB f z e = do
@@ -1021,8 +1286,8 @@ mapAccumMaybeMB f z e = do
1021 return $ case result of
1286 return $ case result of
1022 (Nothing, Nothing) -> Nothing
1287 (Nothing, Nothing) -> Nothing
1023 _ -> Just result
1288 _ -> Just result
1024− d' <- hold z $ fmapMaybe fst e'
1289+ d' <- hold z $ mapMaybe fst e'
1025− return (d', fmapMaybe snd e')
1290+ return (d', mapMaybe snd e')
1027-- | Accumulate occurrences of an 'Event', producing an output occurrence each
1292-- | Accumulate occurrences of an 'Event', producing an output occurrence each
1028-- time. Discard the underlying 'Accumulator'.
1293-- time. Discard the underlying 'Accumulator'.
@@ -1069,7 +1334,7 @@ instance Reflex t => Accumulator t (Event t) where
1069 accumMaybeM f z e = updated <$> accumMaybeM f z e
1334 accumMaybeM f z e = updated <$> accumMaybeM f z e
1070 mapAccumMaybeM f z e = first updated <$> mapAccumMaybeM f z e
1335 mapAccumMaybeM f z e = first updated <$> mapAccumMaybeM f z e
1072−-- | Create a new 'Event' by combining each occurence with the next value of the
1337+-- | Create a new 'Event' by combining each occurrence with the next value of the
1073-- list using the supplied function. If the list runs out of items, all
1338-- list using the supplied function. If the list runs out of items, all
1074-- subsequent 'Event' occurrences will be ignored.
1339-- subsequent 'Event' occurrences will be ignored.
1075zipListWithEvent :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> c) -> [a] -> Event t b -> m (Event t c)
1340zipListWithEvent :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> c) -> [a] -> Event t b -> m (Event t c)
@@ -1079,20 +1344,20 @@ zipListWithEvent f l e = do
1079 _ -> (Nothing, Nothing) --TODO: Unsubscribe the event?
1344 _ -> (Nothing, Nothing) --TODO: Unsubscribe the event?
1080 mapAccumMaybe_ f' l e
1345 mapAccumMaybe_ f' l e
1082−-- | Assign a number to each occurence of the given 'Event', starting from 0
1347+-- | Assign a number to each occurrence of the given 'Event', starting from 0
1083{-# INLINE numberOccurrences #-}
1348{-# INLINE numberOccurrences #-}
1084numberOccurrences :: (Reflex t, MonadHold t m, MonadFix m, Num b) => Event t a -> m (Event t (b, a))
1349numberOccurrences :: (Reflex t, MonadHold t m, MonadFix m, Num b) => Event t a -> m (Event t (b, a))
1085numberOccurrences = numberOccurrencesFrom 0
1350numberOccurrences = numberOccurrencesFrom 0
1087−-- | Assign a number to each occurence of the given 'Event'
1352+-- | Assign a number to each occurrence of the given 'Event'
1088{-# INLINE numberOccurrencesFrom #-}
1353{-# INLINE numberOccurrencesFrom #-}
1089numberOccurrencesFrom :: (Reflex t, MonadHold t m, MonadFix m, Num b) => b -> Event t a -> m (Event t (b, a))
1354numberOccurrencesFrom :: (Reflex t, MonadHold t m, MonadFix m, Num b) => b -> Event t a -> m (Event t (b, a))
1090−numberOccurrencesFrom = mapAccum_ (\n a -> (n + 1, (n, a)))
1355+numberOccurrencesFrom = mapAccum_ (\n a -> let !next = n + 1 in (next, (n, a)))
1092−-- | Assign a number to each occurence of the given 'Event'; discard the occurrences' values
1357+-- | Assign a number to each occurrence of the given 'Event'; discard the occurrences' values
1093{-# INLINE numberOccurrencesFrom_ #-}
1358{-# INLINE numberOccurrencesFrom_ #-}
1094numberOccurrencesFrom_ :: (Reflex t, MonadHold t m, MonadFix m, Num b) => b -> Event t a -> m (Event t b)
1359numberOccurrencesFrom_ :: (Reflex t, MonadHold t m, MonadFix m, Num b) => b -> Event t a -> m (Event t b)
1095−numberOccurrencesFrom_ = mapAccum_ (\n _ -> (n + 1, n))
1360+numberOccurrencesFrom_ = mapAccum_ (\n _ -> let !next = n + 1 in (next, n))
1097-- | This is used to sample the value of a 'Behavior' using an 'Event'.
1362-- | This is used to sample the value of a 'Behavior' using an 'Event'.
@@ -1162,83 +1427,57 @@ infixl 4 <@>
1162(<@) = tag
1427(<@) = tag
1163infixl 4 <@
1428infixl 4 <@
1169−-- | A 'Monad' that supports adjustment over time. After an action has been
1170−-- run, if the given events fire, it will adjust itself so that its net effect
1171−-- is as though it had originally been run with the new value. Note that there
1172−-- is some issue here with persistent side-effects: obviously, IO (and some
1173−-- other side-effects) cannot be undone, so it is up to the instance implementer
1174−-- to determine what the best meaning for this class is in such cases.
1175−class (Reflex t, Monad m) => Adjustable t m | m -> t where
1176− runWithReplace :: m a -> Event t (m b) -> m (a, Event t b)
1177− traverseIntMapWithKeyWithAdjust :: (IntMap.Key -> v -> m v') -> IntMap v -> Event t (PatchIntMap v) -> m (IntMap v', Event t (PatchIntMap v'))
1178− traverseDMapWithKeyWithAdjust :: GCompare k => (forall a. k a -> v a -> m (v' a)) -> DMap k v -> Event t (PatchDMap k v) -> m (DMap k v', Event t (PatchDMap k v'))
1179− traverseDMapWithKeyWithAdjustWithMove :: GCompare k => (forall a. k a -> v a -> m (v' a)) -> DMap k v -> Event t (PatchDMapWithMove k v) -> m (DMap k v', Event t (PatchDMapWithMove k v'))
1181−instance Adjustable t m => Adjustable t (ReaderT r m) where
1182− runWithReplace a0 a' = do
1184− lift $ runWithReplace (runReaderT a0 r) $ fmap (`runReaderT` r) a'
1185− traverseIntMapWithKeyWithAdjust f dm0 dm' = do
1187− lift $ traverseIntMapWithKeyWithAdjust (\k v -> runReaderT (f k v) r) dm0 dm'
1188− traverseDMapWithKeyWithAdjust f dm0 dm' = do
1190− lift $ traverseDMapWithKeyWithAdjust (\k v -> runReaderT (f k v) r) dm0 dm'
1191− traverseDMapWithKeyWithAdjustWithMove f dm0 dm' = do
1193− lift $ traverseDMapWithKeyWithAdjustWithMove (\k v -> runReaderT (f k v) r) dm0 dm'
1195−sequenceDMapWithAdjust :: (GCompare k, Adjustable t m) => DMap k m -> Event t (PatchDMap k m) -> m (DMap k Identity, Event t (PatchDMap k Identity))
1196−sequenceDMapWithAdjust = traverseDMapWithKeyWithAdjust $ \_ -> fmap Identity
1198−sequenceDMapWithAdjustWithMove :: (GCompare k, Adjustable t m) => DMap k m -> Event t (PatchDMapWithMove k m) -> m (DMap k Identity, Event t (PatchDMapWithMove k Identity))
1199−sequenceDMapWithAdjustWithMove = traverseDMapWithKeyWithAdjustWithMove $ \_ -> fmap Identity
1201−mapMapWithAdjustWithMove :: forall t m k v v'. (Adjustable t m, Ord k) => (k -> v -> m v') -> Map k v -> Event t (PatchMapWithMove k v) -> m (Map k v', Event t (PatchMapWithMove k v'))
1202−mapMapWithAdjustWithMove f m0 m' = do
1203− (out0 :: DMap (Const2 k v) (Constant v'), out') <- traverseDMapWithKeyWithAdjustWithMove (\(Const2 k) (Identity v) -> Constant <$> f k v) (mapToDMap m0) (const2PatchDMapWithMoveWith Identity <$> m')
1204− return (dmapToMapWith (\(Constant v') -> v') out0, patchDMapWithMoveToPatchMapWithMoveWith (\(Constant v') -> v') <$> out')
1206------------------
1430------------------
1207-- Cheap Functions
1431-- Cheap Functions
1208------------------
1432------------------
1434+-- | A "cheap" version of 'pushAlways'. See the performance note on 'pushCheap'.
1210{-# INLINE pushAlwaysCheap #-}
1435{-# INLINE pushAlwaysCheap #-}
1211pushAlwaysCheap :: Reflex t => (a -> PushM t b) -> Event t a -> Event t b
1436pushAlwaysCheap :: Reflex t => (a -> PushM t b) -> Event t a -> Event t b
1212pushAlwaysCheap f = pushCheap (fmap Just . f)
1437pushAlwaysCheap f = pushCheap (fmap Just . f)
1439+-- | A "cheap" version of 'mapMaybe'. See the performance note on 'pushCheap'.
1440+{-# INLINE mapMaybeCheap #-}
1441+mapMaybeCheap :: Reflex t => (a -> Maybe b) -> Event t a -> Event t b
1442+mapMaybeCheap f = pushCheap $ return . f
1444+-- | An alias for 'mapMaybeCheap'
1214{-# INLINE fmapMaybeCheap #-}
1445{-# INLINE fmapMaybeCheap #-}
1215fmapMaybeCheap :: Reflex t => (a -> Maybe b) -> Event t a -> Event t b
1446fmapMaybeCheap :: Reflex t => (a -> Maybe b) -> Event t a -> Event t b
1216−fmapMaybeCheap f = pushCheap $ return . f
1447+fmapMaybeCheap = mapMaybeCheap
1450+-- | A "cheap" version of 'fforMaybe'. See the performance note on 'pushCheap'.
1218{-# INLINE fforMaybeCheap #-}
1451{-# INLINE fforMaybeCheap #-}
1219fforMaybeCheap :: Reflex t => Event t a -> (a -> Maybe b) -> Event t b
1452fforMaybeCheap :: Reflex t => Event t a -> (a -> Maybe b) -> Event t b
1220−fforMaybeCheap = flip fmapMaybeCheap
1453+fforMaybeCheap = flip mapMaybeCheap
1455+-- | A "cheap" version of 'ffor'. See the performance note on 'pushCheap'.
1222{-# INLINE fforCheap #-}
1456{-# INLINE fforCheap #-}
1223fforCheap :: Reflex t => Event t a -> (a -> b) -> Event t b
1457fforCheap :: Reflex t => Event t a -> (a -> b) -> Event t b
1224fforCheap = flip fmapCheap
1458fforCheap = flip fmapCheap
1460+-- | A "cheap" version of 'fmap'. See the performance note on 'pushCheap'.
1226{-# INLINE fmapCheap #-}
1461{-# INLINE fmapCheap #-}
1227fmapCheap :: Reflex t => (a -> b) -> Event t a -> Event t b
1462fmapCheap :: Reflex t => (a -> b) -> Event t a -> Event t b
1228fmapCheap f = pushCheap $ return . Just . f
1463fmapCheap f = pushCheap $ return . Just . f
1465+-- | A "cheap" version of 'tag'. See the performance note on 'pushCheap'.
1230{-# INLINE tagCheap #-}
1466{-# INLINE tagCheap #-}
1231tagCheap :: Reflex t => Behavior t b -> Event t a -> Event t b
1467tagCheap :: Reflex t => Behavior t b -> Event t a -> Event t b
1232tagCheap b = pushAlwaysCheap $ \_ -> sample b
1468tagCheap b = pushAlwaysCheap $ \_ -> sample b
1470+-- | A "cheap" version of 'mergeWithCheap'. See the performance note on 'pushCheap'.
1234{-# INLINE mergeWithCheap #-}
1471{-# INLINE mergeWithCheap #-}
1235mergeWithCheap :: Reflex t => (a -> a -> a) -> [Event t a] -> Event t a
1472mergeWithCheap :: Reflex t => (a -> a -> a) -> [Event t a] -> Event t a
1236mergeWithCheap = mergeWithCheap' id
1473mergeWithCheap = mergeWithCheap' id
1475+-- | A "cheap" version of 'mergeWithCheap''. See the performance note on 'pushCheap'.
1238{-# INLINE mergeWithCheap' #-}
1476{-# INLINE mergeWithCheap' #-}
1239mergeWithCheap' :: Reflex t => (a -> b) -> (b -> b -> b) -> [Event t a] -> Event t b
1477mergeWithCheap' :: Reflex t => (a -> b) -> (b -> b -> b) -> [Event t a] -> Event t b
1240mergeWithCheap' f g = mergeWithFoldCheap' $ foldl1 g . fmap f
1478mergeWithCheap' f g = mergeWithFoldCheap' $ foldl1 g . fmap f
1480+-- | A "cheap" version of 'mergeWithFoldCheap''. See the performance note on 'pushCheap'.
1242{-# INLINE mergeWithFoldCheap' #-}
1481{-# INLINE mergeWithFoldCheap' #-}
1243mergeWithFoldCheap' :: Reflex t => (NonEmpty a -> b) -> [Event t a] -> Event t b
1482mergeWithFoldCheap' :: Reflex t => (NonEmpty a -> b) -> [Event t a] -> Event t b
1244mergeWithFoldCheap' f es =
1483mergeWithFoldCheap' f es =
@@ -1251,27 +1490,9 @@ mergeWithFoldCheap' f es =
1251-- Deprecated functions
1490-- Deprecated functions
1252--------------------------------------------------------------------------------
1491--------------------------------------------------------------------------------
1254−{-# DEPRECATED MonadAdjust "Use Adjustable instead" #-}
1493+{-# DEPRECATED switchPromptly "Use 'switchHoldPromptly' instead. The 'switchHold*' naming convention was chosen because those functions are more closely related to each other than they are to 'switch'. " #-}
1255−type MonadAdjust = Adjustable
1257−-- | Create a new 'Event' that occurs if at least one of the supplied 'Event's
1258−-- occurs. If both occur at the same time they are combined using 'mappend'.
1259−{-# DEPRECATED appendEvents "If a 'Semigroup a' instance is available, use 'mappend'; otherwise, use 'alignWith (mergeThese mappend)' instead" #-}
1260−appendEvents :: (Reflex t, Monoid a) => Event t a -> Event t a -> Event t a
1494+switchPromptly :: (Reflex t, MonadHold t m) => Event t a -> Event t (Event t a) -> m (Event t a)
1261−appendEvents = alignWith $ mergeThese mappend
1495+switchPromptly = switchHoldPromptly
1262−
1496+{-# DEPRECATED switchPromptOnly "Use 'switchHoldPromptOnly' instead. The 'switchHold*' naming convention was chosen because those functions are more closely related to each other than they are to 'switch'. " #-}
1263−-- | Alias for 'headE'
1497+switchPromptOnly :: (Reflex t, MonadHold t m) => Event t a -> Event t (Event t a) -> m (Event t a)
1264−{-# DEPRECATED onceE "Use 'headE' instead" #-}
1498+switchPromptOnly = switchHoldPromptOnly
1265−onceE :: (Reflex t, MonadHold t m, MonadFix m) => Event t a -> m (Event t a)
1268−-- | Run both sides of a 'These' monadically, combining the results.
1269−{-# DEPRECATED sequenceThese "Use bisequenceA or bisequence from the bifunctors package instead" #-}
1270−#ifdef USE_TEMPLATE_HASKELL
1271−{-# ANN sequenceThese "HLint: ignore Use fmap" #-}
1273−sequenceThese :: Monad m => These (m a) (m b) -> m (These a b)
1274−sequenceThese t = case t of
1275− This ma -> fmap This ma
1276− These ma mb -> liftM2 These ma mb
1277− That mb -> fmap That mb