on develop help sign in
Merge pull request #295 from reflex-frp/aa-haddock-coverage

Some more haddocks

commit376cded87b6de2b883844ff7a6b720c3f9c408eb authorAli Abrar <aliabrar@gmail.com> dateFri 29 Mar 2019, 12:41 (8 years ago) parentb394b8e62b3f1b
8 files changed+182−21
src/Data/AppendMap.hs+14−4 src/Data/FastMutableIntMap.hs+17 src/Data/FastWeakBag.hs+1−1 src/Reflex/Adjustable/Class.hs+30−3 src/Reflex/Class.hs+89−9 src/Reflex/Dynamic.hs+6 src/Reflex/DynamicWriter/Class.hs+1 src/Reflex/Query/Class.hs+24−4
src/Data/AppendMap.hs+14−4
@@ -7,10 +7,14 @@
77{-# LANGUAGE ScopedTypeVariables #-}
88{-# LANGUAGE TypeFamilies #-}
99{-# OPTIONS_GHC -fno-warn-orphans #-}
10−-- | 'Data.Map' with a better 'Monoid' instance
11−--
12−-- 'Data.Map' has @mappend = union@, which is left-biased. AppendMap has
13−-- @mappend = unionWith mappend@ instead.
10+-- |
11+-- Module:
12+-- Data.AppendMap
13+-- Description:
14+-- Instances and convenience functions for 'Data.Map.Monoidal'. We use
15+-- monoidal-containers to take advantage of its better monoid instance.
16+-- 'Data.Map' has @mappend = union@, which is left-biased. 'MonoidalMap'
17+-- has @mappend = unionWith mappend@ instead.
1418module Data.AppendMap
1519 ( module Data.AppendMap
1620 , module Data.Map.Monoidal
@@ -30,12 +34,15 @@ import qualified Data.Witherable as W
3034import Data.Map.Monoidal
3135
3236{-# DEPRECATED AppendMap "Use 'MonoidalMap' instead" #-}
37+-- | AppendMap is a synonym for 'Data.Map.Monoidal.MonoidalMap'
3338type AppendMap = MonoidalMap
3439
3540{-# DEPRECATED _unAppendMap "Use 'getMonoidalMap' instead" #-}
41+-- | A synonym for 'getMonoidalMap'
3642_unAppendMap :: MonoidalMap k v -> Map k v
3743_unAppendMap = getMonoidalMap
3844
45+-- | Pattern synonym for 'MonoidalMap'
3946pattern AppendMap :: Map k v -> MonoidalMap k v
4047pattern AppendMap m = MonoidalMap m
4148
@@ -50,6 +57,7 @@ nonEmptyDelete k vs =
5057 then Nothing
5158 else Just deleted
5259
60+-- | Like 'mapMaybe' but indicates whether the resulting container is empty
5361mapMaybeNoNull :: (a -> Maybe b)
5462 -> MonoidalMap token a
5563 -> Maybe (MonoidalMap token b)
@@ -60,9 +68,11 @@ mapMaybeNoNull f as =
6068 else Just bs
6169
6270-- TODO: Move instances to `Reflex.Patch`
71+-- | Displays a 'MonoidalMap' as a tree. See 'Data.Map.Lazy.showTree' for details.
6372showTree :: forall k a. (Show k, Show a) => MonoidalMap k a -> String
6473showTree = coerce (Map.showTree :: Map k a -> String)
6574
75+-- | Displays a 'MonoidalMap' as a tree, using the supplied function to convert nodes to string.
6676showTreeWith :: forall k a. (k -> a -> String) -> Bool -> Bool -> MonoidalMap k a -> String
6777showTreeWith = coerce (Map.showTreeWith :: (k -> a -> String) -> Bool -> Bool -> Map k a -> String)
6878
src/Data/FastMutableIntMap.hs+17
@@ -1,4 +1,9 @@
11{-# LANGUAGE TypeFamilies #-}
2+-- |
3+-- Module:
4+-- Data.FastMutableIntMap
5+-- Description:
6+-- A mutable version of 'IntMap'
27module Data.FastMutableIntMap
38 ( FastMutableIntMap
49 , new
@@ -32,33 +37,43 @@ import Data.IORef
3237import Reflex.Patch.Class
3338import Reflex.Patch.IntMap
3439
40+-- | A 'FastMutableIntMap' holds a map of values of type @a@ and allows low-overhead modifications via IO.
41+-- Operations on 'FastMutableIntMap' run in IO.
3542newtype FastMutableIntMap a = FastMutableIntMap (IORef (IntMap a))
3643
44+-- | Create a new 'FastMutableIntMap' out of an 'IntMap'
3745new :: IntMap a -> IO (FastMutableIntMap a)
3846new m = FastMutableIntMap <$> newIORef m
3947
48+-- | Create a new empty 'FastMutableIntMap'
4049newEmpty :: IO (FastMutableIntMap a)
4150newEmpty = FastMutableIntMap <$> newIORef IntMap.empty
4251
52+-- | Insert an element into a 'FastMutableIntMap' at the given key
4353insert :: FastMutableIntMap a -> Int -> a -> IO ()
4454insert (FastMutableIntMap r) k v = modifyIORef' r $ IntMap.insert k v
4555
56+-- | Attempt to lookup an element by key in a 'FastMutableIntMap'
4657lookup :: FastMutableIntMap a -> Int -> IO (Maybe a)
4758lookup (FastMutableIntMap r) k = IntMap.lookup k <$> readIORef r
4859
60+-- | Runs the provided action over the intersection of a 'FastMutableIntMap' and an 'IntMap'
4961forIntersectionWithImmutable_ :: MonadIO m => FastMutableIntMap a -> IntMap b -> (a -> b -> m ()) -> m ()
5062forIntersectionWithImmutable_ (FastMutableIntMap r) b f = do
5163 a <- liftIO $ readIORef r
5264 traverse_ (uncurry f) $ IntMap.intersectionWith (,) a b
5365
66+-- | Runs the provided action over the values of a 'FastMutableIntMap'
5467for_ :: MonadIO m => FastMutableIntMap a -> (a -> m ()) -> m ()
5568for_ (FastMutableIntMap r) f = do
5669 a <- liftIO $ readIORef r
5770 traverse_ f a
5871
72+-- | Checks whether a 'FastMutableIntMap' is empty
5973isEmpty :: FastMutableIntMap a -> IO Bool
6074isEmpty (FastMutableIntMap r) = IntMap.null <$> readIORef r
6175
76+-- | Retrieves the size of a 'FastMutableIntMap'
6277size :: FastMutableIntMap a -> IO Int
6378size (FastMutableIntMap r) = IntMap.size <$> readIORef r
6479
@@ -69,6 +84,8 @@ getFrozenAndClear (FastMutableIntMap r) = do
6984 writeIORef r IntMap.empty
7085 return result
7186
87+-- | Updates the value of a 'FastMutableIntMap' with the given patch (see 'Reflex.Patch.IntMap'),
88+-- and returns an 'IntMap' with the modified keys and values.
7289applyPatch :: FastMutableIntMap a -> PatchIntMap a -> IO (IntMap a)
7390applyPatch (FastMutableIntMap r) p@(PatchIntMap m) = do
7491 v <- readIORef r
src/Data/FastWeakBag.hs+1−1
@@ -50,7 +50,7 @@ newtype FastWeakBag a = FastWeakBag JSVal
5050#else
5151data FastWeakBag a = FastWeakBag
5252 { _weakBag_nextId :: {-# UNPACK #-} !(IORef Int) --TODO: what if this wraps around?
53− , _weakBag_children :: {-# UNPACK #-} !(IORef (IntMap (Weak a)))
53+ , _weakBag_children :: {-# UNPACK #-} !(IORef (IntMap (Weak a))) -- ^ Map of items contained by the 'FastWeakBag'
5454 }
5555#endif
5656
src/Reflex/Adjustable/Class.hs+30−3
@@ -11,6 +11,13 @@
1111#ifdef USE_REFLEX_OPTIMIZER
1212{-# OPTIONS_GHC -fplugin=Reflex.Optimizer #-}
1313#endif
14+-- |
15+-- Module:
16+-- Reflex.Adjustable.Class
17+-- Description:
18+-- A class for actions that can be "adjusted" over time based on some 'Event'
19+-- such that, when observed after the firing of any such 'Event', the result
20+-- is as though the action was originally run with the 'Event's value.
1421module Reflex.Adjustable.Class
1522 (
1623 -- * The Adjustable typeclass
@@ -94,13 +101,32 @@ instance Adjustable t m => Adjustable t (ReaderT r m) where
94101 r <- ask
95102 lift $ traverseDMapWithKeyWithAdjustWithMove (\k v -> runReaderT (f k v) r) dm0 dm'
96103
97−sequenceDMapWithAdjust :: (GCompare k, Adjustable t m) => DMap k m -> Event t (PatchDMap k m) -> m (DMap k Identity, Event t (PatchDMap k Identity))
104+-- | Traverse a 'DMap' of 'Adjustable' actions, running each of them. The provided 'Event' of patches
105+-- to the 'DMap' can add, remove, or update values.
106+sequenceDMapWithAdjust
107+ :: (GCompare k, Adjustable t m)
108+ => DMap k m
109+ -> Event t (PatchDMap k m)
110+ -> m (DMap k Identity, Event t (PatchDMap k Identity))
98111sequenceDMapWithAdjust = traverseDMapWithKeyWithAdjust $ \_ -> fmap Identity
99112
100−sequenceDMapWithAdjustWithMove :: (GCompare k, Adjustable t m) => DMap k m -> Event t (PatchDMapWithMove k m) -> m (DMap k Identity, Event t (PatchDMapWithMove k Identity))
113+-- | Traverses a 'DMap' of 'Adjustable' actions, running each of them. The provided 'Event' of patches
114+-- to the 'DMap' can add, remove, update, move, or swap values.
115+sequenceDMapWithAdjustWithMove
116+ :: (GCompare k, Adjustable t m)
117+ => DMap k m
118+ -> Event t (PatchDMapWithMove k m)
119+ -> m (DMap k Identity, Event t (PatchDMapWithMove k Identity))
101120sequenceDMapWithAdjustWithMove = traverseDMapWithKeyWithAdjustWithMove $ \_ -> fmap Identity
102121
103−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'))
122+-- | Traverses a 'Map', running the provided 'Adjustable' action. The provided 'Event' of patches to the 'Map'
123+-- can add, remove, update, move, or swap values.
124+mapMapWithAdjustWithMove
125+ :: forall t m k v v'. (Adjustable t m, Ord k)
126+ => (k -> v -> m v')
127+ -> Map k v
128+ -> Event t (PatchMapWithMove k v)
129+ -> m (Map k v', Event t (PatchMapWithMove k v'))
104130mapMapWithAdjustWithMove f m0 m' = do
105131 (out0 :: DMap (Const2 k v) (Constant v'), out') <- traverseDMapWithKeyWithAdjustWithMove (\(Const2 k) (Identity v) -> Constant <$> f k v) (mapToDMap m0) (const2PatchDMapWithMoveWith Identity <$> m')
106132 return (dmapToMapWith (\(Constant v') -> v') out0, patchDMapWithMoveToPatchMapWithMoveWith (\(Constant v') -> v') <$> out')
@@ -110,4 +136,5 @@ mapMapWithAdjustWithMove f m0 m' = do
110136--------------------------------------------------------------------------------
111137
112138{-# DEPRECATED MonadAdjust "Use Adjustable instead" #-}
139+-- | Synonym for 'Adjustable'
113140type MonadAdjust = Adjustable
src/Reflex/Class.hs+89−9
@@ -300,6 +300,8 @@ class ( MonadHold t (PushM t)
300300 fanInt :: Event t (IntMap a) -> EventSelectorInt t a
301301
302302--TODO: Specialize this so that we can take advantage of knowing that there's no changing going on
303+-- | Constructs a single 'Event' out of a map of events. The output event may fire with multiple
304+-- keys simultaneously.
303305mergeInt :: Reflex t => IntMap (Event t a) -> Event t (IntMap a)
304306mergeInt m = mergeIntIncremental $ unsafeBuildIncremental (return m) never
305307
@@ -368,26 +370,91 @@ class MonadSample t m => MonadHold t m where
368370 -- the supplied 'Event'.
369371 headE :: Event t a -> m (Event t a)
370372
371−accumIncremental :: (Reflex t, Patch p, MonadHold t m, MonadFix m) => (PatchTarget p -> b -> p) -> PatchTarget p -> Event t b -> m (Incremental t p)
373+-- | Accumulate an 'Incremental' with the supplied initial value and the firings of the provided 'Event',
374+-- using the combining function to produce a patch.
375+accumIncremental
376+ :: (Reflex t, Patch p, MonadHold t m, MonadFix m)
377+ => (PatchTarget p -> b -> p)
378+ -> PatchTarget p
379+ -> Event t b
380+ -> m (Incremental t p)
372381accumIncremental 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)
382+
383+-- | Similar to 'accumIncremental' but the combining function runs in 'PushM'
384+accumMIncremental
385+ :: (Reflex t, Patch p, MonadHold t m, MonadFix m)
386+ => (PatchTarget p -> b -> PushM t p)
387+ -> PatchTarget p
388+ -> Event t b
389+ -> m (Incremental t p)
374390accumMIncremental 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)
391+
392+-- | Similar to 'accumIncremental' but allows filtering of updates (by dropping updates when the
393+-- combining function produces @Nothing@)
394+accumMaybeIncremental
395+ :: (Reflex t, Patch p, MonadHold t m, MonadFix m)
396+ => (PatchTarget p -> b -> Maybe p)
397+ -> PatchTarget p
398+ -> Event t b
399+ -> m (Incremental t p)
376400accumMaybeIncremental 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)
401+
402+-- | Similar to 'accumMaybeMIncremental' but the combining function runs in 'PushM'
403+accumMaybeMIncremental
404+ :: (Reflex t, Patch p, MonadHold t m, MonadFix m)
405+ => (PatchTarget p -> b -> PushM t (Maybe p))
406+ -> PatchTarget p
407+ -> Event t b
408+ -> m (Incremental t p)
378409accumMaybeMIncremental f z e = do
379410 rec let e' = flip push e $ \o -> do
380411 v <- sample $ currentIncremental d'
381412 f v o
382413 d' <- holdIncremental z e'
383414 return d'
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)
415+
416+-- | Accumulate an 'Incremental' by folding occurrences of an 'Event'
417+-- with a function that both accumulates and produces a value to fire
418+-- as an 'Event'. Returns both the accumulated value and the constructed
419+-- 'Event'.
420+mapAccumIncremental
421+ :: (Reflex t, Patch p, MonadHold t m, MonadFix m)
422+ => (PatchTarget p -> b -> (p, c))
423+ -> PatchTarget p
424+ -> Event t b
425+ -> m (Incremental t p, Event t c)
385426mapAccumIncremental 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)
427+
428+-- | Like 'mapAccumIncremental' but the combining function runs in 'PushM'
429+mapAccumMIncremental
430+ :: (Reflex t, Patch p, MonadHold t m, MonadFix m)
431+ => (PatchTarget p -> b -> PushM t (p, c))
432+ -> PatchTarget p
433+ -> Event t b
434+ -> m (Incremental t p, Event t c)
387435mapAccumMIncremental 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)
436+
437+-- | Accumulate an 'Incremental' by folding occurrences of an 'Event' with
438+-- a function that both optionally accumulates and optionally produces
439+-- a value to fire as a separate output 'Event'.
440+-- Note that because 'Nothing's are discarded in both cases, the output
441+-- 'Event' may fire even though the output 'Incremental' has not changed, and
442+-- the output 'Incremental' may update even when the output 'Event' is not firing.
443+mapAccumMaybeIncremental
444+ :: (Reflex t, Patch p, MonadHold t m, MonadFix m)
445+ => (PatchTarget p -> b -> (Maybe p, Maybe c))
446+ -> PatchTarget p
447+ -> Event t b
448+ -> m (Incremental t p, Event t c)
389449mapAccumMaybeIncremental 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)
450+
451+-- | Like 'mapAccumMaybeIncremental' but the combining function is a 'PushM' action
452+mapAccumMaybeMIncremental
453+ :: (Reflex t, Patch p, MonadHold t m, MonadFix m)
454+ => (PatchTarget p -> b -> PushM t (Maybe p, Maybe c))
455+ -> PatchTarget p
456+ -> Event t b
457+ -> m (Incremental t p, Event t c)
391458mapAccumMaybeMIncremental f z e = do
392459 rec let e' = flip push e $ \o -> do
393460 v <- sample $ currentIncremental d'
@@ -398,6 +465,7 @@ mapAccumMaybeMIncremental f z e = do
398465 d' <- holdIncremental z $ mapMaybe fst e'
399466 return (d', mapMaybe snd e')
400467
468+-- | A somewhat slow implementation of 'headE'
401469slowHeadE :: (Reflex t, MonadHold t m, MonadFix m) => Event t a -> m (Event t a)
402470slowHeadE e = do
403471 rec be <- hold e $ fmapCheap (const never) e'
@@ -418,6 +486,8 @@ newtype EventSelector t k = EventSelector
418486 select :: forall a. k a -> Event t a
419487 }
420488
489+-- | Efficiently select an 'Event' keyed on 'Int'. This is more efficient than manually
490+-- filtering by key.
421491newtype EventSelectorInt t a = EventSelectorInt { selectInt :: Int -> Event t a }
422492
423493--------------------------------------------------------------------------------
@@ -801,7 +871,12 @@ mergeList :: Reflex t => [Event t a] -> Event t (NonEmpty a)
801871mergeList [] = never
802872mergeList es = mergeWithFoldCheap' id es
803873
804−unsafeMapIncremental :: (Reflex t, Patch p, Patch p') => (PatchTarget p -> PatchTarget p') -> (p -> p') -> Incremental t p -> Incremental t p'
874+unsafeMapIncremental
875+ :: (Reflex t, Patch p, Patch p')
876+ => (PatchTarget p -> PatchTarget p')
877+ -> (p -> p')
878+ -> Incremental t p
879+ -> Incremental t p'
805880unsafeMapIncremental f g a = unsafeBuildIncremental (fmap f $ sample $ currentIncremental a) $ g <$> updatedIncremental a
806881
807882-- | Create a new 'Event' combining the map of 'Event's into an 'Event' that
@@ -918,6 +993,9 @@ coincidencePatchMapWithMove e = fmapCheap unsafePatchMapWithMove $ coincidence $
918993 ni { PatchMapWithMove._nodeInfo_from = PatchMapWithMove.From_Delete }
919994 ]
920995
996+-- | Given a 'PatchTarget' of events (e.g., a 'Map' with 'Event' values) and an event of 'Patch'es
997+-- (e.g., a 'PatchMap' with 'Event' values), produce an 'Event' of the 'PatchTarget' type that
998+-- fires with the patched value.
921999switchHoldPromptOnlyIncremental
9221000 :: forall t m p pt w
9231001 . ( Reflex t
@@ -1491,8 +1569,10 @@ mergeWithFoldCheap' f es =
14911569--------------------------------------------------------------------------------
14921570
14931571{-# 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'. " #-}
1572+-- | See 'switchHoldPromptly'
14941573switchPromptly :: (Reflex t, MonadHold t m) => Event t a -> Event t (Event t a) -> m (Event t a)
14951574switchPromptly = switchHoldPromptly
14961575{-# 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'. " #-}
1576+-- | See 'switchHoldPromptOnly'
14971577switchPromptOnly :: (Reflex t, MonadHold t m) => Event t a -> Event t (Event t a) -> m (Event t a)
14981578switchPromptOnly = switchHoldPromptOnly
src/Reflex/Dynamic.hs+6
@@ -301,6 +301,8 @@ maybeDyn = fmap (fmap unpack) . eitherDyn . fmap pack
301301 Left _ -> Nothing
302302 Right a -> Just a
303303
304+-- | Turns a 'Dynamic t (Either a b)' into a 'Dynamic t (Either (Dynamic t a) (Dynamic t b))' such that
305+-- the outer 'Dynamic' is updated only when the 'Either' constructor changes (e.g., from 'Left' to 'Right').
304306eitherDyn :: forall t a b m. (Reflex t, MonadFix m, MonadHold t m) => Dynamic t (Either a b) -> m (Dynamic t (Either (Dynamic t a) (Dynamic t b)))
305307eitherDyn = fmap (fmap unpack) . factorDyn . fmap eitherToDSum
306308 where unpack :: DSum (EitherTag a b) (Compose (Dynamic t) Identity) -> Either (Dynamic t a) (Dynamic t b)
@@ -308,6 +310,9 @@ eitherDyn = fmap (fmap unpack) . factorDyn . fmap eitherToDSum
308310 LeftTag :=> Compose a -> Left $ coerceDynamic a
309311 RightTag :=> Compose b -> Right $ coerceDynamic b
310312
313+-- | Factor a 'Dynamic t DSum' into a 'Dynamic' 'DSum' containing nested 'Dynamic' values.
314+-- The outer 'Dynamic' updates only when the key of the 'DSum' changes, while the update of the inner
315+-- 'Dynamic' represents updates within the current key.
311316factorDyn :: forall t m k v. (Reflex t, MonadHold t m, GEq k)
312317 => Dynamic t (DSum k v) -> m (Dynamic t (DSum k (Compose (Dynamic t) v)))
313318factorDyn d = buildDynamic (sample (current d) >>= holdKey) update where
@@ -322,6 +327,7 @@ factorDyn d = buildDynamic (sample (current d) >>= holdKey) update where
322327 inner' <- filterEventKey k (updated d)
323328 inner <- holdDyn v inner'
324329 return $ k :=> Compose inner
330+
325331--------------------------------------------------------------------------------
326332-- Demux
327333--------------------------------------------------------------------------------
src/Reflex/DynamicWriter/Class.hs+1
@@ -17,6 +17,7 @@ import Control.Monad.Reader (ReaderT, lift)
1717import Reflex.Class (Dynamic)
1818
1919{-# DEPRECATED MonadDynamicWriter "Use 'DynamicWriter' instead" #-}
20+-- | Type synonym for 'DynamicWriter'
2021type MonadDynamicWriter = DynamicWriter
2122
2223-- | 'MonadDynamicWriter' efficiently collects 'Dynamic' values using 'tellDyn'
src/Reflex/Query/Class.hs+24−4
@@ -6,6 +6,13 @@
66{-# LANGUAGE MultiParamTypeClasses #-}
77{-# LANGUAGE TypeFamilies #-}
88{-# LANGUAGE UndecidableInstances #-}
9+-- |
10+-- Module:
11+-- Reflex.Query.Class
12+-- Description:
13+-- A class that ties together queries to some data source and their results,
14+-- providing methods for requesting data from the source and accumulating
15+-- streamed results.
916module Reflex.Query.Class
1017 ( Query (..)
1118 , QueryMorphism (..)
@@ -32,6 +39,10 @@ import Foreign.Storable
3239
3340import Reflex.Class
3441
42+-- | A 'Query' can be thought of as a declaration of interest in some set of data.
43+-- A 'QueryResult' is the set of data associated with that interest set.
44+-- The @crop@ function provides a way to determine what part of a given 'QueryResult'
45+-- is relevant to a given 'Query'.
3546class (Monoid (QueryResult a), Semigroup (QueryResult a)) => Query a where
3647 type QueryResult a :: *
3748 crop :: a -> QueryResult a -> QueryResult a
@@ -40,8 +51,8 @@ instance (Ord k, Query v) => Query (MonoidalMap k v) where
4051 type QueryResult (MonoidalMap k v) = MonoidalMap k (QueryResult v)
4152 crop q r = MonoidalMap.intersectionWith (flip crop) r q
4253
43−-- | NB: QueryMorphism's must be group homomorphisms when acting on the query type
44−-- and compatible with the query relationship when acting on the query result
54+-- | QueryMorphism's must be group homomorphisms when acting on the query type
55+-- and compatible with the query relationship when acting on the query result.
4556data QueryMorphism q q' = QueryMorphism
4657 { _queryMorphism_mapQuery :: q -> q'
4758 , _queryMorphism_mapQueryResult :: QueryResult q' -> QueryResult q
@@ -54,13 +65,16 @@ instance Category QueryMorphism where
5465 , _queryMorphism_mapQueryResult = mapQueryResult qm' . mapQueryResult qm
5566 }
5667
68+-- | Apply a 'QueryMorphism' to a 'Query'
5769mapQuery :: QueryMorphism q q' -> q -> q'
5870mapQuery = _queryMorphism_mapQuery
5971
72+-- | Map a 'QueryMorphism' to a 'QueryResult'
6073mapQueryResult :: QueryMorphism q q' -> QueryResult q' -> QueryResult q
6174mapQueryResult = _queryMorphism_mapQueryResult
6275
63−-- | This type keeps track of the multiplicity of elements of the view selector that are being used by the app
76+-- | This type can be used to track of the frequency of interest in a given 'Query'. See note on
77+-- 'combineSelectedCounts'
6478newtype SelectedCount = SelectedCount { unSelectedCount :: Int }
6579 deriving (Eq, Ord, Show, Read, Integral, Num, Bounded, Enum, Real, Ix, Bits, FiniteBits, Storable, Data)
6680
@@ -76,10 +90,14 @@ instance Group SelectedCount where
7690
7791instance Additive SelectedCount
7892
79−-- | The Semigroup/Monoid/Group instances for a ViewSelector should use this function which returns Nothing if the result is 0. This allows the pruning of leaves that are no longer wanted.
93+-- | The Semigroup/Monoid/Group instances for a Query containing 'SelectedCount's should use
94+-- this function which returns Nothing if the result is 0. This allows the pruning of leaves
95+-- of the 'Query' that are no longer wanted.
8096combineSelectedCounts :: SelectedCount -> SelectedCount -> Maybe SelectedCount
8197combineSelectedCounts (SelectedCount i) (SelectedCount j) = if i == negate j then Nothing else Just $ SelectedCount (i + j)
8298
99+-- | A class that allows sending of 'Query's and retrieval of 'QueryResult's. See 'queryDyn' for a commonly
100+-- used interface.
83101class (Group q, Additive q, Query q) => MonadQuery t q m | m -> q t where
84102 tellQueryIncremental :: Incremental t (AdditivePatch q) -> m ()
85103 askQueryResult :: m (Dynamic t (QueryResult q))
@@ -90,9 +108,11 @@ instance (Monad m, MonadQuery t q m) => MonadQuery t q (ReaderT r m) where
90108 askQueryResult = lift askQueryResult
91109 queryIncremental = lift . queryIncremental
92110
111+-- | Produce and send an 'Incremental' 'Query' from a 'Dynamic' 'Query'.
93112tellQueryDyn :: (Reflex t, MonadQuery t q m) => Dynamic t q -> m ()
94113tellQueryDyn d = tellQueryIncremental $ unsafeBuildIncremental (sample (current d)) $ attachWith (\old new -> AdditivePatch $ new ~~ old) (current d) (updated d)
95114
115+-- | Retrieve 'Dynamic'ally updating 'QueryResult's for a 'Dynamic'ally updating 'Query'.
96116queryDyn :: (Reflex t, Monad m, MonadQuery t q m) => Dynamic t q -> m (Dynamic t (QueryResult q))
97117queryDyn q = do
98118 tellQueryDyn q