1{-# language DataKinds #-}
2{-# language DeriveFunctor #-}
3{-# language DerivingStrategies #-}
4{-# language FlexibleContexts #-}
5{-# language FlexibleInstances #-}
6{-# language MultiParamTypeClasses #-}
7{-# language NamedFieldPuns #-}
8{-# language ScopedTypeVariables #-}
9{-# language StandaloneKindSignatures #-}
10{-# language TupleSections #-}
11{-# language TypeApplications #-}
12{-# language TypeFamilies #-}
13{-# language UndecidableInstances #-}
15{-# options_ghc -fno-warn-orphans #-}
17module Rel8.Table.These
19 , theseTable, thisTable, thatTable, thoseTable
20 , isThisTable, isThatTable, isThoseTable
21 , hasHereTable, hasThereTable
22 , justHereTable, justThereTable
29import Control.Category ( id )
30import Data.Bifunctor ( Bifunctor, bimap )
31import Data.Kind ( Type )
32import Data.Maybe ( isJust )
33import Data.Type.Equality ( apply )
34import Prelude hiding ( id, undefined )
37import Rel8.Aggregate ( Aggregate )
38import Rel8.Expr ( Expr )
39import Rel8.Expr.Bool ( (&&.), not_ )
40import Rel8.Expr.Null ( isNonNull )
41import Rel8.Kind.Context ( Reifiable )
42import Rel8.Schema.Context.Abstract ( Abstract )
43import Rel8.Schema.Context.Nullify ( Nullifiable )
44import Rel8.Schema.Dict ( Dict( Dict ) )
45import Rel8.Schema.HTable.Label ( hlabel, hunlabel )
46import Rel8.Schema.HTable.Identity ( HIdentity(..) )
47import Rel8.Schema.HTable.These ( HTheseTable(..) )
48import qualified Rel8.Schema.Kind as K
49import Rel8.Schema.Name ( Name )
51 ( Table, Columns, Context, fromColumns, toColumns
52 , coherence, congruence, reify, unreify
54import Rel8.Table.Eq ( EqTable, eqTable )
55import Rel8.Table.Maybe
57 , maybeTable, justTable, nothingTable
62import Rel8.Table.Nullify ( Nullify, guard )
63import Rel8.Table.Ord ( OrdTable, ordTable )
64import Rel8.Table.Recontextualize ( Recontextualize )
65import Rel8.Table.Serialize ( FromExprs, ToExprs, fromResult, toResult )
66import Rel8.Table.Undefined ( undefined )
67import Rel8.Type.Tag ( MaybeTag )
70import Data.Functor.Apply ( Apply, (<.>) )
71import Data.Functor.Bind ( Bind, (>>-) )
74import Data.These ( These )
77-- | @TheseTable a b@ is a Rel8 table that contains either the table @a@, the
78-- table @b@, or both tables @a@ and @b@. You can construct @TheseTable@s using
79-- 'thisTable', 'thatTable' and 'thoseTable'. @TheseTable@s can be
80-- eliminated/pattern matched using 'theseTable'.
82-- @TheseTable@ is operationally the same as Haskell's 'These' type, but
83-- adapted to work with Rel8.
84type TheseTable :: K.Context -> Type -> Type -> Type
85data TheseTable context a b = TheseTable
86 { here :: MaybeTable context a
87 , there :: MaybeTable context b
89 deriving stock Functor
92instance Nullifiable context => Bifunctor (TheseTable context) where
93 bimap f g (TheseTable a b) = TheseTable (fmap f a) (fmap g b)
96instance (context ~ Expr, Table Expr a, Semigroup a) =>
97 Apply (TheseTable context a)
99 fs <.> as = TheseTable
100 { here = here fs <> here as
101 , there = there fs <.> there as
105instance (context ~ Expr, Table Expr a, Semigroup a) =>
106 Applicative (TheseTable context a)
112instance (context ~ Expr, Table Expr a, Semigroup a) =>
113 Bind (TheseTable context a)
115 TheseTable here1 ma >>- f = case ma >>- f' of
117 { here = maybeTable here1 ((here1 <>) . fst) mtb
118 , there = snd <$> mtb
122 TheseTable here2 mb -> (here2,) <$> mb
125instance (context ~ Expr, Table Expr a, Semigroup a) =>
126 Monad (TheseTable context a)
131instance (context ~ Expr, Table Expr a, Table Expr b, Semigroup a, Semigroup b) =>
132 Semigroup (TheseTable context a b)
135 { here = here a <> here b
136 , there = there a <> there b
141 ( Table context a, Table context b
142 , Reifiable context, Abstract context, context ~ context'
144 => Table context' (TheseTable context a b)
146 type Columns (TheseTable context a b) = HTheseTable (Columns a) (Columns b)
147 type Context (TheseTable context a b) = Context a
149 toColumns TheseTable {here, there} = HTheseTable
150 { hhereTag = hlabel $ HIdentity $ tag here
152 hlabel $ guard (tag here) isJust isNonNull $ toColumns $ just here
153 , hthereTag = hlabel $ HIdentity $ tag there
155 hlabel $ guard (tag there) isJust isNonNull $ toColumns $ just there
158 fromColumns HTheseTable {hhereTag, hhere, hthereTag, hthere} = TheseTable
160 { tag = unHIdentity $ hunlabel hhereTag
161 , just = fromColumns $ hunlabel hhere
164 { tag = unHIdentity $ hunlabel hthereTag
165 , just = fromColumns $ hunlabel hthere
169 reify proof TheseTable {here, there} = TheseTable
170 { here = reify proof here
171 , there = reify proof there
173 unreify proof TheseTable {here, there} = TheseTable
174 { here = unreify proof here
175 , there = unreify proof there
178 coherence = coherence @context @a
179 congruence proof abstract =
181 congruence @context @a proof abstract `apply`
182 congruence @context @b proof abstract
186 ( Reifiable from, Abstract from, from ~ from'
187 , Reifiable to, Abstract to, to ~ to'
188 , Recontextualize from to a1 b1
189 , Recontextualize from to a2 b2
191 => Recontextualize from to (TheseTable from' a1 a2) (TheseTable to' b1 b2)
194instance (EqTable a, EqTable b, context ~ Expr) =>
195 EqTable (TheseTable context a b)
197 eqTable = HTheseTable
198 { hhereTag = hlabel (HType Dict)
199 , hhere = hlabel (eqTable @(Nullify context a))
200 , hthereTag = hlabel (HType Dict)
201 , hthere = hlabel (eqTable @(Nullify context b))
205instance (OrdTable a, OrdTable b, context ~ Expr) =>
206 OrdTable (TheseTable context a b)
208 ordTable = HTheseTable
209 { hhereTag = hlabel (HType Dict)
210 , hhere = hlabel (ordTable @(Nullify context a))
211 , hthereTag = hlabel (HType Dict)
212 , hthere = hlabel (ordTable @(Nullify context b))
216type instance FromExprs (TheseTable _context a b) =
217 These (FromExprs a) (FromExprs b)
220instance (ToExprs exprs1 a, ToExprs exprs2 b, x ~ TheseTable Expr exprs1 exprs2) =>
221 ToExprs x (These a b)
224 bimap (fromResult @exprs1) (fromResult @exprs2) .
228 bimap (toResult @exprs1) (toResult @exprs2)
231-- | Test if a 'TheseTable' was constructed with 'thisTable'.
233-- Corresponds to 'Data.These.Combinators.isThis'.
234isThisTable :: TheseTable Expr a b -> Expr Bool
235isThisTable a = hasHereTable a &&. not_ (hasThereTable a)
238-- | Test if a 'TheseTable' was constructed with 'thatTable'.
240-- Corresponds to 'Data.These.Combinators.isThat'.
241isThatTable :: TheseTable Expr a b -> Expr Bool
242isThatTable a = not_ (hasHereTable a) &&. hasThereTable a
245-- | Test if a 'TheseTable' was constructed with 'thoseTable'.
247-- Corresponds to 'Data.These.Combinators.isThese'.
248isThoseTable :: TheseTable Expr a b -> Expr Bool
249isThoseTable a = hasHereTable a &&. hasThereTable a
252-- | Test if the @a@ side of @TheseTable a b@ is present.
254-- Corresponds to 'Data.These.Combinators.hasHere'.
255hasHereTable :: TheseTable Expr a b -> Expr Bool
256hasHereTable TheseTable {here} = isJustTable here
259-- | Test if the @b@ table of @TheseTable a b@ is present.
261-- Corresponds to 'Data.These.Combinators.hasThere'.
262hasThereTable :: TheseTable Expr a b -> Expr Bool
263hasThereTable TheseTable {there} = isJustTable there
266-- | Attempt to project out the @a@ table of a @TheseTable a b@.
268-- Corresponds to 'Data.These.Combinators.justHere'.
269justHereTable :: TheseTable context a b -> MaybeTable context a
273-- | Attempt to project out the @b@ table of a @TheseTable a b@.
275-- Corresponds to 'Data.These.Combinators.justThere'.
276justThereTable :: TheseTable context a b -> MaybeTable context b
277justThereTable = there
280-- | Construct a @TheseTable@. Corresponds to 'This'.
281thisTable :: Table Expr b => a -> TheseTable Expr a b
282thisTable a = TheseTable (justTable a) nothingTable
285-- | Construct a @TheseTable@. Corresponds to 'That'.
286thatTable :: Table Expr a => b -> TheseTable Expr a b
287thatTable b = TheseTable nothingTable (justTable b)
290-- | Construct a @TheseTable@. Corresponds to 'These'.
291thoseTable :: a -> b -> TheseTable Expr a b
292thoseTable a b = TheseTable (justTable a) (justTable b)
295-- | Pattern match on a 'TheseTable'. Corresponds to 'these'.
296theseTable :: Table Expr c
297 => (a -> c) -> (b -> c) -> (a -> b -> c) -> TheseTable Expr a b -> c
298theseTable f g h TheseTable {here, there} =
300 (maybeTable undefined f here)
301 (\b -> maybeTable (g b) (`h` b) here)
305-- | Lift a pair of aggregating functions to operate on an 'TheseTable'.
306-- @thisTable@s, @thatTable@s and @thoseTable@s are grouped separately.
307aggregateTheseTable :: ()
308 => (exprs -> aggregates)
309 -> (exprs' -> aggregates')
310 -> TheseTable Expr exprs exprs'
311 -> TheseTable Aggregate aggregates aggregates'
312aggregateTheseTable f g (TheseTable here there) = TheseTable
313 { here = aggregateMaybeTable f here
314 , there = aggregateMaybeTable g there
318-- | Construct a 'TheseTable' in the 'Name' context. This can be useful if you
319-- have a 'TheseTable' that you are storing in a table and need to construct a
322 => Name (Maybe MaybeTag)
323 -- ^ The name of the column to track the presence of the @a@ table.
324 -> Name (Maybe MaybeTag)
325 -- ^ The name of the column to track the presence of the @b@ table.
327 -- ^ Names of the columns in the @a@ table.
329 -- ^ Names of the columns in the @b@ table.
330 -> TheseTable Name a b
331nameTheseTable here there a b =
333 { here = nameMaybeTable here a
334 , there = nameMaybeTable there b
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