on develop help sign in
Merge branch 'develop' into cleanup-debug
commitfabac7d5a993d0e9ba6cc6901596be4da6356192 authorJames Deikun <james.deikun@obsidian.systems> dateThu 16 Jan 2020, 18:52 (7 years ago) parent948fe914f13ad4
3 files changed+43−1
ChangeLog.md+2 reflex.cabal+1−1 src/Reflex/Query/Class.hs+40
ChangeLog.md+2
@@ -9,6 +9,8 @@
99* The `Reflex.Patch.*` modules were moved to the `patch` library.
1010 They are `Data.Patch.*` there, but reexported under their old names for backwards compatability here.
1111
12+* Additional instances for `Query` classes for basic types.
13+
1214## 0.6.3
1315
1416* `Data.WeakBag.traverse` and `Data.FastWeakBag.traverse` have been deprecated.
reflex.cabal+1−1
@@ -72,7 +72,7 @@ library
7272 lens >= 4.7 && < 5,
7373 monad-control >= 1.0.1 && < 1.1,
7474 mtl >= 2.1 && < 2.3,
75− patch >= 0.0 && < 0.1,
75+ patch >= 0.0.1 && < 0.1,
7676 prim-uniq >= 0.1.0.1 && < 0.2,
7777 primitive >= 0.5 && < 0.8,
7878 profunctors >= 5.3 && < 5.6,
src/Reflex/Query/Class.hs+40
@@ -1,3 +1,4 @@
1+{-# LANGUAGE CPP #-}
12{-# LANGUAGE DeriveDataTypeable #-}
23{-# LANGUAGE FlexibleContexts #-}
34{-# LANGUAGE FlexibleInstances #-}
@@ -21,6 +22,7 @@ module Reflex.Query.Class
2122 , MonadQuery (..)
2223 , tellQueryDyn
2324 , queryDyn
25+ , subQuery
2426 , mapQuery
2527 , mapQueryResult
2628 ) where
@@ -35,6 +37,9 @@ import Data.Map.Monoidal (MonoidalMap)
3537import qualified Data.Map.Monoidal as MonoidalMap
3638import Data.Semigroup (Semigroup(..))
3739import Foreign.Storable
40+import Data.Void
41+import Data.Monoid hiding ((<>))
42+import Control.Applicative
3843
3944import Reflex.Class
4045
@@ -50,6 +55,37 @@ instance (Ord k, Query v) => Query (MonoidalMap k v) where
5055 type QueryResult (MonoidalMap k v) = MonoidalMap k (QueryResult v)
5156 crop q r = MonoidalMap.intersectionWith (flip crop) r q
5257
58+-- | the result of two queries is both results.
59+instance (Query a, Query b) => Query (a, b) where
60+ type QueryResult (a, b) = (QueryResult a, QueryResult b)
61+ crop (x, x') (y, y') = (crop x y, crop x' y')
62+
63+-- | Trivial queries have trivial results.
64+instance Query () where
65+ type QueryResult () = ()
66+ crop _ _ = ()
67+
68+-- | The result of an absurd query is trivial; If you can ask the question, the
69+-- answer cannot tell you anything you didn't already know.
70+--
71+-- 'QueryResult Void = @Void@' seems like it would also work, but that has
72+-- problems of robustness. In some applications, an unasked question can still
73+-- be answered, so it is important that the result is inhabited even when the
74+-- question isn't. Applications that wish to prevent this can mandate that the
75+-- query result be paired with the query: then the whole response will be
76+-- uninhabited as desired.
77+instance Query Void where
78+ type QueryResult Void = ()
79+ crop = absurd
80+
81+#if MIN_VERSION_base(4,12,0)
82+-- | We can lift queries into monoidal containers.
83+-- But beware of Applicatives whose monoid is different from (pure mempty, liftA2 mappend)
84+instance (Query q, Applicative f) => Query (Ap f q) where
85+ type QueryResult (Ap f q) = Ap f (QueryResult q)
86+ crop = liftA2 crop
87+#endif
88+
5389-- | QueryMorphism's must be group homomorphisms when acting on the query type
5490-- and compatible with the query relationship when acting on the query result.
5591data QueryMorphism q q' = QueryMorphism
@@ -116,3 +152,7 @@ queryDyn :: (Reflex t, Monad m, MonadQuery t q m) => Dynamic t q -> m (Dynamic t
116152queryDyn q = do
117153 tellQueryDyn q
118154 zipDynWith crop q <$> askQueryResult
155+
156+-- | Use a query morphism to operate on a smaller version of a query.
157+subQuery :: (Reflex t, MonadQuery t q2 m, Monad m) => QueryMorphism q1 q2 -> Dynamic t q1 -> m (Dynamic t (QueryResult q1))
158+subQuery (QueryMorphism f g) x = fmap g <$> queryDyn (fmap f x)