on develop help sign in
Merge branch 'cocreature-doc-class' into develop
commit93c247a49a0e2440a488274fa1a6ec22917bc213 authorRyan Trinkle <ryan.trinkle@gmail.com> dateThu 30 Apr 2015, 05:24 (11 years ago) parent7dbb59030bb668
1 file changed+68−5
src/Reflex/Class.hs+68−5
src/Reflex/Class.hs+68−5
@@ -70,9 +70,12 @@ instance MonadHold t m => MonadHold t (ReaderT r m) where
7070-- Convenience functions
7171--------------------------------------------------------------------------------
7272
73+-- | Create an Event from another Event.
74+-- The provided function can sample 'Behavior's and hold 'Event's.
7375pushAlways :: Reflex t => (a -> PushM t b) -> Event t a -> Event t b
7476pushAlways f e = push (liftM Just . f) e
7577
78+-- | Flipped version of 'fmap'.
7679ffor :: Functor f => f a -> (a -> b) -> f b
7780ffor = flip fmap
7881
@@ -80,12 +83,17 @@ instance Reflex t => Functor (Behavior t) where
8083 fmap f = pull . liftM f . sample
8184
8285--TODO: See if there's a better class in the standard libraries already
86+-- | A class for values that combines filtering and mapping using 'Maybe'.
8387class FunctorMaybe f where
88+ -- | Combined mapping and filtering function.
8489 fmapMaybe :: (a -> Maybe b) -> f a -> f b
8590
91+-- | Flipped version of 'fmapMaybe'.
8692fforMaybe :: FunctorMaybe f => f a -> (a -> Maybe b) -> f b
8793fforMaybe = flip fmapMaybe
8894
95+-- | Filter 'f a' using the provided predicate.
96+-- Relies on 'fforMaybe'.
8997ffilter :: FunctorMaybe f => (a -> Bool) -> f a -> f a
9098ffilter f = fmapMaybe $ \x -> if f x then Just x else Nothing
9199
@@ -95,6 +103,9 @@ instance Reflex t => FunctorMaybe (Event t) where
95103instance Reflex t => Functor (Event t) where
96104 fmap f = fmapMaybe $ Just . f
97105
106+-- | Create a new 'Event' by combining each occurence with the next value
107+-- of the list using the supplied function. If the list runs out of items,
108+-- all subsequent 'Event' occurrences will be ignored.
98109zipListWithEvent :: (Reflex t, MonadHold t m, MonadFix m) => (a -> b -> c) -> [a] -> Event t b -> m (Event t c)
99110zipListWithEvent f l e = do
100111 rec lb <- hold l eTail
@@ -107,22 +118,33 @@ zipListWithEvent f l e = do
107118 lb `seq` eBoth `seq` eTail `seq` return ()
108119 return $ fmap fst eBoth
109120
110−-- | Replace the occurrence value of the Event with the value of the Behavior at the time of the occurrence
121+-- | Replace each occurrence value of the 'Event' with the value of the
122+-- 'Behavior' at the time of that occurrence.
111123tag :: Reflex t => Behavior t b -> Event t a -> Event t b
112124tag b = pushAlways $ \_ -> sample b
113125
114−attachWithMaybe :: Reflex t => (a -> b -> Maybe c) -> Behavior t a -> Event t b -> Event t c
115−attachWithMaybe f b e = flip push e $ \o -> liftM (flip f o) $ sample b
126+-- | Create a new 'Event' that combines occurences of supplied 'Event'
127+-- with the current value of the 'Behavior'.
128+attach :: Reflex t => Behavior t a -> Event t b -> Event t (a, b)
129+attach = attachWith (,)
116130
131+-- | Create a new 'Event' that occurs when the supplied 'Event' occurs
132+-- by combining it with the current value of the 'Behavior'.
117133attachWith :: Reflex t => (a -> b -> c) -> Behavior t a -> Event t b -> Event t c
118134attachWith f = attachWithMaybe $ \a b -> Just $ f a b
119135
120−attach :: Reflex t => Behavior t a -> Event t b -> Event t (a, b)
121−attach = attachWith (,)
136+-- | Create a new 'Event' by combining each occurence with the current
137+-- value of the 'Behavior'. The occurrence is discarded if the combining function
138+-- returns Nothing
139+attachWithMaybe :: Reflex t => (a -> b -> Maybe c) -> Behavior t a -> Event t b -> Event t c
140+attachWithMaybe f b e = flip push e $ \o -> liftM (flip f o) $ sample b
122141
142+-- | Alias for 'headE'
123143onceE :: (Reflex t, MonadHold t m, MonadFix m) => Event t a -> m (Event t a)
124144onceE = headE
125145
146+-- | Create a new 'Event' that only occurs on the first occurence of
147+-- the supplied 'Event'.
126148headE :: (Reflex t, MonadHold t m, MonadFix m) => Event t a -> m (Event t a)
127149headE e = do
128150 rec be <- hold e $ fmap (const never) e'
@@ -130,24 +152,42 @@ headE e = do
130152 e' `seq` return ()
131153 return e'
132154
155+-- | Create a new 'Event' that occurs on all but the first occurence
156+-- of the supplied 'Event'.
133157tailE :: (Reflex t, MonadHold t m, MonadFix m) => Event t a -> m (Event t a)
134158tailE e = liftM snd $ headTailE e
135159
160+-- | Create a tuple of two 'Event's with the first one occuring only
161+-- the first time the supplied 'Event' occurs and the second occuring
162+-- on all but the first occurence.
136163headTailE :: (Reflex t, MonadHold t m, MonadFix m) => Event t a -> m (Event t a, Event t a)
137164headTailE e = do
138165 eHead <- headE e
139166 be <- hold never $ fmap (const e) eHead
140167 return (eHead, switch be)
141168
169+-- | Split the supplied 'Event' into two individual 'Event's occuring
170+-- at the same time with the respective values from the tuple.
142171splitE :: Reflex t => Event t (a, b) -> (Event t a, Event t b)
143172splitE e = (fmap fst e, fmap snd e)
144173
174+-- | Print the supplied 'String' and the value of the 'Event' on each
175+-- occurence. This should /only/ be used for debugging.
176+--
177+-- Note: As with Debug.Trace.trace, the message will only be printed if
178+-- the 'Event' is actually used.
145179traceEvent :: (Reflex t, Show a) => String -> Event t a -> Event t a
146180traceEvent s = traceEventWith $ \x -> s <> ": " <> show x
147181
182+-- | Print the output of the supplied function on each occurence of
183+-- the 'Event'. This should /only/ be used for debugging.
184+--
185+-- Note: As with Debug.Trace.trace, the message will only be printed if
186+-- the 'Event' is actually used.
148187traceEventWith :: Reflex t => (a -> String) -> Event t a -> Event t a
149188traceEventWith f = push $ \x -> trace (f x) $ return $ Just x
150189
190+-- | Tag type for 'Either' to use it as a 'DSum'.
151191data EitherTag l r a where
152192 LeftTag :: EitherTag l r l
153193 RightTag :: EitherTag l r r
@@ -175,16 +215,19 @@ instance (Show l, Show r) => ShowTag (EitherTag l r) where
175215 LeftTag -> showsPrec n a
176216 RightTag -> showsPrec n a
177217
218+-- | Convert 'Either' to a 'DSum'. Inverse of 'dsumToEither'.
178219eitherToDSum :: Either a b -> DSum (EitherTag a b)
179220eitherToDSum = \case
180221 Left a -> LeftTag :=> a
181222 Right b -> RightTag :=> b
182223
224+-- | Convert 'DSum' to 'Either'. Inverse of 'eitherToDSum'.
183225dsumToEither :: DSum (EitherTag a b) -> Either a b
184226dsumToEither = \case
185227 LeftTag :=> a -> Left a
186228 RightTag :=> b -> Right b
187229
230+-- | Extract the values of a 'DMap' of 'EitherTag's.
188231dmapToThese :: DMap (EitherTag a b) -> Maybe (These a b)
189232dmapToThese m = case (DMap.lookup LeftTag m, DMap.lookup RightTag m) of
190233 (Nothing, Nothing) -> Nothing
@@ -192,9 +235,13 @@ dmapToThese m = case (DMap.lookup LeftTag m, DMap.lookup RightTag m) of
192235 (Nothing, Just b) -> Just $ That b
193236 (Just a, Just b) -> Just $ These a b
194237
238+-- | Create a new 'Event' that occurs if at least one of the supplied
239+-- 'Event's occurs. If both occur at the same time they are combined
240+-- using 'mappend'.
195241appendEvents :: (Reflex t, Monoid a) => Event t a -> Event t a -> Event t a
196242appendEvents e1 e2 = fmap (mergeThese mappend) $ align e1 e2
197243
244+{-# DEPRECATED sequenceThese "Use bisequenceA or bisequence from the bifunctors package instead" #-}
198245sequenceThese :: Monad m => These (m a) (m b) -> m (These a b)
199246sequenceThese t = case t of
200247 This ma -> liftM This ma
@@ -206,19 +253,33 @@ instance (Semigroup a, Reflex t) => Monoid (Event t a) where
206253 mappend a b = mconcat [a, b]
207254 mconcat = fmap sconcat . mergeList
208255
256+-- | Create a new 'Event' that occurs if at least one of the 'Event's
257+-- in the list occurs. If multiple occur at the same time they are
258+-- folded from the left with the given function.
209259mergeWith :: Reflex t => (a -> a -> a) -> [Event t a] -> Event t a
210260mergeWith f es = fmap (Prelude.foldl1 f . map (\(Const2 _ :=> v) -> v) . DMap.toList) $ merge $ DMap.fromList $ map (\(k, v) -> WrapArg (Const2 k) :=> v) $ zip [0 :: Int ..] es
211261
262+-- | Create a new 'Event' that occurs if at least one of the 'Event's
263+-- in the list occurs. If multiple occur at the same time the value is
264+-- the value of the leftmost event.
212265leftmost :: Reflex t => [Event t a] -> Event t a
213266leftmost = mergeWith const
214267
268+-- | Create a new 'Event' that occurs if at least one of the 'Event's
269+-- in the list occurs and has a list of the values of all 'Event's
270+-- occuring at that time.
215271mergeList :: Reflex t => [Event t a] -> Event t (NonEmpty a)
216272mergeList [] = never
217273mergeList es = mergeWith (<>) $ map (fmap (:|[])) es
218274
275+-- | Create a new 'Event' combining the map of 'Event's into an
276+-- 'Event' that occurs if at least one of them occurs and has a map of
277+-- values of all 'Event's occuring at that time.
219278mergeMap :: (Reflex t, Ord k) => Map k (Event t a) -> Event t (Map k a)
220279mergeMap = fmap dmapToMap . merge . mapWithFunctorToDMap
221280
281+-- | Split the event into an 'EventSelector' that allows efficient
282+-- selection of the individual 'Event's.
222283fanMap :: (Reflex t, Ord k) => Event t (Map k a) -> EventSelector t (Const2 k a)
223284fanMap = fan . fmap mapToDMap
224285
@@ -234,5 +295,7 @@ instance Reflex t => Align (Event t) where
234295 nil = never
235296 align ea eb = fmapMaybe dmapToThese $ merge $ DMap.fromList [WrapArg LeftTag :=> ea, WrapArg RightTag :=> eb]
236297
298+-- | Create a new 'Event' that only occurs if the supplied 'Event'
299+-- occurs and the 'Behavior' is true at the time of occurence.
237300gate :: Reflex t => Behavior t Bool -> Event t a -> Event t a
238301gate = attachWithMaybe $ \allow a -> if allow then Just a else Nothing