1{-# language AllowAmbiguousTypes #-}
2{-# language ConstraintKinds #-}
3{-# language DataKinds #-}
4{-# language DefaultSignatures #-}
5{-# language FlexibleContexts #-}
6{-# language FlexibleInstances #-}
7{-# language MultiParamTypeClasses #-}
8{-# language ScopedTypeVariables #-}
9{-# language StandaloneKindSignatures #-}
10{-# language TypeApplications #-}
11{-# language TypeFamilies #-}
12{-# language UndecidableInstances #-}
14module Rel8.Generic.Rel8able
18 , GColumns, GContext, gfromColumns, gtoColumns
19 , GColumnsADT, gfromColumnsADT, gtoColumnsADT
25import Data.Kind ( Constraint, Type )
26import Data.Proxy ( Proxy( Proxy ) )
27import Data.Type.Equality ( (:~:)( Refl ) )
28import GHC.Generics ( Generic, Rep, from, to )
32import Rel8.Kind.Context ( Reifiable )
33import Rel8.FCF ( Eval, Exp )
34import Rel8.Generic.Map ( GMap, GMappable, gmap, gunmap )
35import Rel8.Generic.Record ( Record(..) )
36import Rel8.Generic.Table
37 ( GGTable, GGColumns, GGContext, ggfromColumns, ggtoColumns
40import qualified Rel8.Generic.Table.ADT as G
41import Rel8.Kind.Algebra
42 ( SAlgebra( SProduct, SSum )
43 , KnownAlgebra, algebraSing
45import qualified Rel8.Kind.Algebra as K ( Algebra(..) )
46import Rel8.Schema.Context ( Col )
47import Rel8.Schema.Context.Label ( Labelable )
48import Rel8.Schema.HTable ( HTable )
49import qualified Rel8.Schema.Kind as K
50import Rel8.Schema.Name ( Name )
51import Rel8.Schema.Reify ( Col( Reify ), Reify, UnwrapReify )
52import Rel8.Schema.Result ( Result )
54 ( fromColumns, toColumns, reify, unreify
55 , TTable, TColumns, TContext, TUnreify
60type KRel8able = K.Rel8able
63-- | This type class allows you to define custom 'Table's using higher-kinded
64-- data types. Higher-kinded data types are data types of the pattern:
68-- MyType { field1 :: Column f T1 OR HK1 f
69-- , field2 :: Column f T2 OR HK2 f
71-- , fieldN :: Column f Tn OR HKn f
75-- where @Tn@ is any Haskell type, and @HKn@ is any higher-kinded type.
77-- That is, higher-kinded data are records where all fields in the record are
78-- all either of the type @Column f T@ (for any @T@), or are themselves
85-- Nested { nested1 :: MyType f
86-- , nested2 :: MyType f
90-- The @Rel8able@ type class is used to give us a special mapping operation
91-- that lets us change the type parameter @f@.
93-- [Supplying @Rel8able@ instances]
95-- This type class should be derived generically for all table types in your
96-- project. To do this, enable the @DeriveAnyType@ and @DeriveGeneric@ language
100-- \{\-\# LANGUAGE DeriveAnyClass, DeriveGeneric #-\}
102-- data MyType f = MyType { fieldA :: Column f T }
103-- deriving ( GHC.Generics.Generic, Rel8able )
105type Rel8able :: K.Rel8able -> Constraint
107 ( HTable (GColumns t)
108 , HTable (GColumnsADT t)
109 , GContext t Result ~ Result
113 type Algebra t :: K.Algebra
115 type GRep t (context :: K.Context) :: Type -> Type
117 type GColumns t :: K.HTable
119 type GContext t (context :: K.Context) :: K.Context
121 gfromColumns :: (Labelable context, Reifiable context, GContext t context ~ context)
122 => GColumns t (Col (Reify context)) -> t (Reify context)
124 gtoColumns :: (Labelable context, Reifiable context, GContext t context ~ context)
125 => t (Reify context) -> GColumns t (Col (Reify context))
127 gfromColumnsADT :: GColumnsADT t (Col (Reify Result)) -> t (Reify Result)
129 gtoColumnsADT :: t (Reify Result) -> GColumnsADT t (Col (Reify Result))
131 greify :: (Labelable context, Reifiable context)
132 => t context -> t (Reify context)
134 gunreify :: (Labelable context, Reifiable context)
135 => t (Reify context) -> t context
137 type Algebra t = GAlgebra (GRep t (Reify Name))
139 type GRep t context = Rep (Record (t context))
141 type GColumns t = Eval (GGColumns (Algebra t) TColumns (GRep t (Reify Name)))
143 type GContext t context =
144 Eval (GGContext (Algebra t) TUnreifyContext (GRep t (Reify context)))
146 default gfromColumns :: forall context.
147 ( Generic (Record (t (Reify context)))
148 , GRep t (Reify context) ~ Rep (Record (t (Reify context)))
149 , KnownAlgebra (Algebra t)
150 , Eval (GGTable (Algebra t) (TTable (Reify context)) TColumns (Col (Reify context)) (GRep t (Reify context)))
151 , Eval (GGColumns (Algebra t) TColumns (GRep t (Reify context))) ~ GColumns t
152 , Constraints t context
154 => GColumns t (Col (Reify context)) -> t (Reify context)
160 @(TTable (Reify context))
163 (fromContext @t @context)
164 (toContext @t @context)
167 default gtoColumns :: forall context.
168 ( Generic (Record (t (Reify context)))
169 , GRep t (Reify context) ~ Rep (Record (t (Reify context)))
170 , KnownAlgebra (Algebra t)
171 , Eval (GGTable (Algebra t) (TTable (Reify context)) TColumns (Col (Reify context)) (GRep t (Reify context)))
172 , Eval (GGColumns (Algebra t) TColumns (GRep t (Reify context))) ~ GColumns t
173 , Constraints t context
175 => t (Reify context) -> GColumns t (Col (Reify context))
179 @(TTable (Reify context))
182 (fromContext @t @context)
183 (toContext @t @context)
188 default gfromColumnsADT ::
189 ( Generic (Record (t (Reify Result)))
190 , GRep t (Reify Result) ~ Rep (Record (t (Reify Result)))
191 , G.GTableADT (TTable (Reify Result)) TColumns (Col (Reify Result)) (GRep t (Reify Result))
192 , G.GColumnsADT TColumns (GRep t (Reify Result)) ~ GColumnsADT t
194 => GColumnsADT t (Col (Reify Result)) -> t (Reify Result)
199 @(TTable (Reify Result))
205 default gtoColumnsADT ::
206 ( Generic (Record (t (Reify Result)))
207 , GRep t (Reify Result) ~ Rep (Record (t (Reify Result)))
208 , G.GTableADT (TTable (Reify Result)) TColumns (Col (Reify Result)) (GRep t (Reify Result))
209 , G.GColumnsADT TColumns (GRep t (Reify Result)) ~ GColumnsADT t
211 => t (Reify Result) -> GColumnsADT t (Col (Reify Result))
214 @(TTable (Reify Result))
222 default greify :: forall context.
223 ( Generic (Record (t context))
224 , GRep t context ~ Rep (Record (t context))
225 , Generic (Record (t (Reify context)))
226 , GRep t (Reify context) ~ Rep (Record (t (Reify context)))
227 , GMappable (TTable (Reify context)) (GRep t (Reify context))
228 , GRep t context ~ GMap TUnreify (GRep t (Reify context))
230 => t context -> t (Reify context)
234 gunmap @(TTable (Reify context)) (Proxy @TUnreify) (reify Refl) .
238 default gunreify :: forall context.
239 ( Generic (Record (t context))
240 , GRep t context ~ Rep (Record (t context))
241 , Generic (Record (t (Reify context)))
242 , GRep t (Reify context) ~ Rep (Record (t (Reify context)))
243 , GMappable (TTable (Reify context)) (GRep t (Reify context))
244 , GRep t context ~ GMap TUnreify (GRep t (Reify context))
246 => t (Reify context) -> t context
250 gmap @(TTable (Reify context)) (Proxy @TUnreify) (unreify Refl) .
255type GColumnsADT t = G.GColumnsADT TColumns (GRep t (Reify Name))
258data TUnreifyContext :: Type -> Exp K.Context
259type instance Eval (TUnreifyContext a) = UnwrapReify (Eval (TContext a))
262type Constraints :: K.Rel8able -> K.Context -> Constraint
263type Constraints t context = Constraints' (Algebra t) t context
266type Constraints' :: K.Algebra -> K.Rel8able -> K.Context -> Constraint
267type family Constraints' algebra t context where
268 Constraints' 'K.Product t context =
269 Eval (GGContext 'K.Product TContext (GRep t (Reify context))) ~
271 Constraints' 'K.Sum _ context = context ~ Result
274fromContext :: forall t context spec.
275 ( KnownAlgebra (Algebra t)
276 , Constraints t context
278 => Col (Reify context) spec
279 -> Col (Eval (GGContext (Algebra t) TContext (GRep t (Reify context)))) spec
280fromContext = case algebraSing @(Algebra t) of
282 SSum -> \(Reify a) -> a
285toContext :: forall t context spec.
286 ( KnownAlgebra (Algebra t)
287 , Constraints t context
289 => Col (Eval (GGContext (Algebra t) TContext (GRep t (Reify context)))) spec
290 -> Col (Reify context) spec
291toContext = case algebraSing @(Algebra t) of
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