1{-# language DeriveFunctor #-}
2{-# language DerivingStrategies #-}
3{-# language FlexibleContexts #-}
4{-# language TupleSections #-}
32import Control.Applicative ( liftA2 )
33import Control.Monad ( join, liftM2 )
34import Data.Bifunctor ( bimap, first )
35import Data.Foldable ( traverse_ )
36import Data.Maybe ( fromMaybe )
37import Prelude hiding ( filter, lookup, undefined, zip, zipWith )
40import Rel8.Aggregate ( Aggregate )
41import Rel8.Expr ( Expr )
42import Rel8.Expr.Bool ( not_, true )
43import Rel8.Query ( Query )
44import Rel8.Query.Aggregate ( aggregate )
45import Rel8.Query.Exists ( withBy, withoutBy )
46import Rel8.Query.Filter ( filter, where_ )
47import Rel8.Query.Maybe ( optional )
48import Rel8.Query.These ( alignBy )
49import Rel8.Schema.Context ( DB )
50import Rel8.Table ( Table )
51import Rel8.Table.Aggregate ( groupBy )
52import Rel8.Table.Eq ( EqTable, (==:) )
53import Rel8.Table.Maybe ( MaybeTable )
54import Rel8.Table.These ( TheseTable, theseTable )
55import Rel8.Table.Undefined ( undefined )
58import Data.Functor.Apply ( Apply, liftF2 )
59import Data.Functor.Bind ( Bind )
60import qualified Data.Functor.Bind
61import Data.Semigroup.Traversable.Class ( bitraverse1 )
64newtype Tabulation k a = Tabulation (k -> Query (Maybe k, a))
65 deriving stock Functor
68instance EqTable k => Apply (Tabulation k) where
72instance EqTable k => Applicative (Tabulation k) where
73 pure = liftQuery . pure
77instance EqTable k => Bind (Tabulation k) where
81instance EqTable k => Monad (Tabulation k) where
82 Tabulation as >>= f = Tabulation $ \i -> do
85 Nothing -> case f a of
91 Nothing -> pure (mk, b)
97runTabulation :: EqTable k => Tabulation k a -> Query (k, a)
98runTabulation (Tabulation f) = do
102 -- Opaleye tries to be too clever optimising "WHERE FALSE" and generates
103 -- invalid SQL, so we use "WHERE NOT TRUE" instead
106 Just k -> pure (k, a)
111liftQuery :: Query a -> Tabulation k a
112liftQuery query = Tabulation $ const $ fmap (Nothing,) query
115tabulate :: (a -> k) -> a -> Tabulation k a
116tabulate key a = fromQuery $ pure (key a, a)
119tabulateA :: (a -> Query k) -> a -> Tabulation k a
120tabulateA key a = fromQuery $ (,a) <$> key a
123fromQuery :: Query (k, a) -> Tabulation k a
124fromQuery = Tabulation . const . fmap (first Just)
127indexed :: Tabulation k a -> Tabulation k (k, a)
128indexed (Tabulation query) = Tabulation $ \i ->
129 (\(mk, a) -> (mk, (fromMaybe i mk, a))) <$> query i
132ifilter :: (k -> a -> Expr Bool) -> Tabulation k a -> Tabulation k a
133ifilter f tabulation = snd <$> do
134 filter (uncurry f) `postbind` indexed tabulation
137prebind :: (a -> Tabulation k b) -> Query a -> Tabulation k b
138prebind f as = Tabulation $ \k -> do
141 Tabulation query -> query k
145postbind :: (a -> Query b) -> Tabulation k a -> Tabulation k b
146postbind f (Tabulation as) = Tabulation $ \i -> do
155lookup :: EqTable k => k -> Tabulation k a -> Query a
156lookup key (Tabulation query) = do
158 traverse_ (where_ . (key ==:)) mk
162align :: (EqTable k, Table DB a, Table DB b)
163 => Tabulation k a -> Tabulation k b -> Tabulation k (TheseTable a b)
167alignWith :: (EqTable k, Table DB a, Table DB b)
168 => (TheseTable a b -> c)
169 -> Tabulation k a -> Tabulation k b -> Tabulation k c
170alignWith f kas kbs = do
174 tkab <- alignBy (\(l, _) (m, _) -> l ==: m) as bs
176 k' = theseTable fst fst (const fst) tkab
177 tab = bimap snd snd tkab
181leftAlign :: EqTable k
182 => Tabulation k a -> Tabulation k b -> Tabulation k (a, MaybeTable b)
183leftAlign = leftAlignWith (,)
186leftAlignWith :: EqTable k
187 => (a -> MaybeTable b -> c)
188 -> Tabulation k a -> Tabulation k b -> Tabulation k c
189leftAlignWith f left right = liftA2 f left (optionalTabulation right)
193 => Tabulation k a -> Tabulation k b -> Tabulation k (a, b)
198 => (a -> b -> c) -> Tabulation k a -> Tabulation k b -> Tabulation k c
202similarity :: EqTable k => Tabulation k a -> Tabulation k b -> Tabulation k a
203similarity kas kbs = do
206 fromQuery $ as >>= withBy (\(k, _) (l, _) -> k ==: l) bs
209difference :: EqTable k => Tabulation k a -> Tabulation k b -> Tabulation k a
210difference kas kbs = do
213 fromQuery $ as >>= withoutBy (\(k, _) (l, _) -> k ==: l) bs
216aggregateTabulation :: EqTable k
217 => Tabulation k (Aggregate a) -> Tabulation k a
218aggregateTabulation kas = do
220 fromQuery $ aggregate $ bitraverse1 groupBy id <$> as
223optionalTabulation :: EqTable k
224 => Tabulation k a -> Tabulation k (MaybeTable a)
225optionalTabulation as = Tabulation $ \k -> do
226 ma <- optional $ lookup k as
230toQuery :: Tabulation k a -> Tabulation k (Query (k, a))
231toQuery (Tabulation as) = Tabulation $ \k ->
232 pure (Nothing, first (fromMaybe k) <$> as k)
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