1{-# LANGUAGE DeriveDataTypeable #-}
2{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE FlexibleInstances #-}
4{-# LANGUAGE FunctionalDependencies #-}
5{-# LANGUAGE GeneralizedNewtypeDeriving #-}
6{-# LANGUAGE MultiParamTypeClasses #-}
7{-# LANGUAGE TypeFamilies #-}
8{-# LANGUAGE UndecidableInstances #-}
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
16module Reflex.Query.Class
20 , combineSelectedCounts
29import Control.Category (Category)
30import qualified Control.Category as Cat
31import Control.Monad.Reader
35import Data.Map.Monoidal (MonoidalMap)
36import qualified Data.Map.Monoidal as MonoidalMap
37import Data.Semigroup (Semigroup(..))
38import Foreign.Storable
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'.
46class (Monoid (QueryResult a), Semigroup (QueryResult a)) => Query a where
47 type QueryResult a :: *
48 crop :: a -> QueryResult a -> QueryResult a
50instance (Ord k, Query v) => Query (MonoidalMap k v) where
51 type QueryResult (MonoidalMap k v) = MonoidalMap k (QueryResult v)
52 crop q r = MonoidalMap.intersectionWith (flip crop) r q
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.
56data QueryMorphism q q' = QueryMorphism
57 { _queryMorphism_mapQuery :: q -> q'
58 , _queryMorphism_mapQueryResult :: QueryResult q' -> QueryResult q
61instance Category QueryMorphism where
62 id = QueryMorphism id id
63 qm . qm' = QueryMorphism
64 { _queryMorphism_mapQuery = mapQuery qm . mapQuery qm'
65 , _queryMorphism_mapQueryResult = mapQueryResult qm' . mapQueryResult qm
68-- | Apply a 'QueryMorphism' to a 'Query'
69mapQuery :: QueryMorphism q q' -> q -> q'
70mapQuery = _queryMorphism_mapQuery
72-- | Map a 'QueryMorphism' to a 'QueryResult'
73mapQueryResult :: QueryMorphism q q' -> QueryResult q' -> QueryResult q
74mapQueryResult = _queryMorphism_mapQueryResult
76-- | This type can be used to track of the frequency of interest in a given 'Query'. See note on
77-- 'combineSelectedCounts'
78newtype SelectedCount = SelectedCount { unSelectedCount :: Int }
79 deriving (Eq, Ord, Show, Read, Integral, Num, Bounded, Enum, Real, Ix, Bits, FiniteBits, Storable, Data)
81instance Semigroup SelectedCount where
82 SelectedCount a <> SelectedCount b = SelectedCount (a + b)
84instance Monoid SelectedCount where
85 mempty = SelectedCount 0
88instance Group SelectedCount where
89 negateG (SelectedCount a) = SelectedCount (negate a)
91instance Additive SelectedCount
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.
96combineSelectedCounts :: SelectedCount -> SelectedCount -> Maybe SelectedCount
97combineSelectedCounts (SelectedCount i) (SelectedCount j) = if i == negate j then Nothing else Just $ SelectedCount (i + j)
99-- | A class that allows sending of 'Query's and retrieval of 'QueryResult's. See 'queryDyn' for a commonly
101class (Group q, Additive q, Query q) => MonadQuery t q m | m -> q t where
102 tellQueryIncremental :: Incremental t (AdditivePatch q) -> m ()
103 askQueryResult :: m (Dynamic t (QueryResult q))
104 queryIncremental :: Incremental t (AdditivePatch q) -> m (Dynamic t (QueryResult q))
106instance (Monad m, MonadQuery t q m) => MonadQuery t q (ReaderT r m) where
107 tellQueryIncremental = lift . tellQueryIncremental
108 askQueryResult = lift askQueryResult
109 queryIncremental = lift . queryIncremental
111-- | Produce and send an 'Incremental' 'Query' from a 'Dynamic' 'Query'.
112tellQueryDyn :: (Reflex t, MonadQuery t q m) => Dynamic t q -> m ()
113tellQueryDyn d = tellQueryIncremental $ unsafeBuildIncremental (sample (current d)) $ attachWith (\old new -> AdditivePatch $ new ~~ old) (current d) (updated d)
115-- | Retrieve 'Dynamic'ally updating 'QueryResult's for a 'Dynamic'ally updating 'Query'.
116queryDyn :: (Reflex t, Monad m, MonadQuery t q m) => Dynamic t q -> m (Dynamic t (QueryResult q))
119 zipDynWith crop q <$> askQueryResult
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list