1{-# language AllowAmbiguousTypes #-}
2{-# language DataKinds #-}
3{-# language DefaultSignatures #-}
4{-# language DisambiguateRecordFields #-}
5{-# language FlexibleContexts #-}
6{-# language FlexibleInstances #-}
7{-# language ScopedTypeVariables #-}
8{-# language StandaloneKindSignatures #-}
9{-# language TypeApplications #-}
10{-# language TypeFamilies #-}
11{-# language TypeOperators #-}
12{-# language UndecidableInstances #-}
13{-# language UndecidableSuperClasses #-}
14{-# language ViewPatterns #-}
17 ( OrdTable( ordTable ), (<:), (<=:), (>:), (>=:), least, greatest
22import Data.Functor.Const ( Const( Const ), getConst )
23import Data.Kind ( Constraint, Type )
24import GHC.Generics ( Rep, (:*:), K1, M1, Meta( MetaSel ), D, C, S )
25import GHC.TypeLits ( KnownSymbol )
26import Prelude hiding ( seq )
29import Rel8.Expr ( Expr, Col(..) )
30import Rel8.Expr.Bool ( (||.), (&&.), false, true )
31import Rel8.Expr.Eq ( (==.) )
32import Rel8.Expr.Ord ( (<.), (>.) )
33import Rel8.Generic.Record ( Record )
34import Rel8.Schema.Context.Label ( hlabeler )
35import Rel8.Schema.Dict ( Dict( Dict ) )
36import Rel8.Schema.HTable
37 ( HTable, HConstrainTable
38 , htabulateA, hfield, hdicts
40import Rel8.Schema.HTable.Label ( HLabel, hlabel )
41import Rel8.Schema.HTable.Product ( HProduct(..) )
42import Rel8.Schema.HTable.Type ( HType(..) )
43import Rel8.Schema.Kind ( Context )
44import Rel8.Schema.Null (Sql)
45import Rel8.Schema.Spec.ConstrainDBType ( ConstrainDBType )
46import Rel8.Table ( Table, Columns, toColumns, GColumns )
47import Rel8.Table.Bool ( bool )
48import Rel8.Table.Eq ( EqTable )
49import Rel8.Type.Eq ( DBEq )
50import Rel8.Type.Ord ( DBOrd )
53-- | The class of 'Table's that can be ordered. Ordering on tables is defined
54-- by their lexicographic ordering of all columns, so this class means "all
55-- columns in a 'Table' have an instance of 'DBOrd'".
56type OrdTable :: Type -> Constraint
57class EqTable a => OrdTable a where
58 ordTable :: Columns a (Dict (ConstrainDBType DBOrd))
61 ( GColumns (Rep (Record a)) ~ Columns a
62 , GOrdTable (Rep (Record a))
64 => Columns a (Dict (ConstrainDBType DBOrd))
65 ordTable = gordTable @(Rep (Record a))
68type GOrdTable :: (Type -> Type) -> Constraint
69class GOrdTable rep where
70 gordTable :: GColumns rep (Dict (ConstrainDBType DBOrd))
73instance GOrdTable rep => GOrdTable (M1 D c rep) where
74 gordTable = gordTable @rep
77instance GOrdTable rep => GOrdTable (M1 C c rep) where
78 gordTable = gordTable @rep
81instance (GOrdTable rep1, GOrdTable rep2) => GOrdTable (rep1 :*: rep2) where
82 gordTable = HProduct (gordTable @rep1) (gordTable @rep2)
88 , GColumns (M1 S meta k1) ~ HLabel label (Columns a)
89 , meta ~ 'MetaSel ('Just label) _su _ss _ds
92 => GOrdTable (M1 S meta k1)
94 gordTable = hlabel hlabeler (ordTable @a)
98 ( Table Expr (t (Expr :: Context))
100 , HConstrainTable (Columns (t Expr)) (ConstrainDBType DBEq)
101 , HConstrainTable (Columns (t Expr)) (ConstrainDBType DBOrd)
105 ordTable = hdicts @(Columns (t f)) @(ConstrainDBType DBOrd)
111 , HConstrainTable t (ConstrainDBType DBEq)
112 , HConstrainTable t (ConstrainDBType DBOrd)
116 ordTable = hdicts @(Columns (t f)) @(ConstrainDBType DBOrd)
119instance Sql DBOrd a => OrdTable (Expr a) where
120 ordTable = HType Dict
123instance (OrdTable a, OrdTable b) => OrdTable (a, b)
126instance (OrdTable a, OrdTable b, OrdTable c) => OrdTable (a, b, c)
129instance (OrdTable a, OrdTable b, OrdTable c, OrdTable d) => OrdTable (a, b, c, d)
132instance (OrdTable a, OrdTable b, OrdTable c, OrdTable d, OrdTable e) =>
133 OrdTable (a, b, c, d, e)
136-- | Test if one 'Table' sorts before another. Corresponds to comparing all
138(<:) :: forall a. OrdTable a => a -> a -> Expr Bool
139(toColumns -> as) <: (toColumns -> bs) =
140 foldr @[] go false $ getConst $ htabulateA $ \field ->
141 case (hfield as field, hfield bs field) of
142 (DB a, DB b) -> case hfield (ordTable @a) field of
143 Dict -> Const [(a <. b, a ==. b)]
145 go (lt, eq) a = lt ||. (eq &&. a)
149-- | Test if one 'Table' sorts before, or is equal to, another. Corresponds to
150-- comparing all columns with '<='.
151(<=:) :: forall a. OrdTable a => a -> a -> Expr Bool
152(toColumns -> as) <=: (toColumns -> bs) =
153 foldr @[] go true $ getConst $ htabulateA $ \field ->
154 case (hfield as field, hfield bs field) of
155 (DB a, DB b) -> case hfield (ordTable @a) field of
156 Dict -> Const [(a <. b, a ==. b)]
158 go (lt, eq) a = lt ||. (eq &&. a)
162-- | Test if one 'Table' sorts after another. Corresponds to comparing all
164(>:) :: forall a. OrdTable a => a -> a -> Expr Bool
165(toColumns -> as) >: (toColumns -> bs) =
166 foldr @[] go false $ getConst $ htabulateA $ \field ->
167 case (hfield as field, hfield bs field) of
168 (DB a, DB b) -> case hfield (ordTable @a) field of
169 Dict -> Const [(a >. b, a ==. b)]
171 go (gt, eq) a = gt ||. (eq &&. a)
175-- | Test if one 'Table' sorts after another. Corresponds to comparing all
177(>=:) :: forall a. OrdTable a => a -> a -> Expr Bool
178(toColumns -> as) >=: (toColumns -> bs) =
179 foldr @[] go true $ getConst $ htabulateA $ \field ->
180 case (hfield as field, hfield bs field) of
181 (DB a, DB b) -> case hfield (ordTable @a) field of
182 Dict -> Const [(a >. b, a ==. b)]
184 go (gt, eq) a = gt ||. (eq &&. a)
188-- | Given two 'Table's, return the table that sorts before the other.
189least :: OrdTable a => a -> a -> a
190least a b = bool a b (a <: b)
193-- | Given two 'Table's, return the table that sorts after the other.
194greatest :: OrdTable a => a -> a -> a
195greatest a b = bool a b (a >: 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