rel8-1.0.0.0: src/Rel8/Column/NonEmpty.hs
{-# language DataKinds #-}
{-# language FlexibleContexts #-}
{-# language LambdaCase #-}
{-# language MultiParamTypeClasses #-}
{-# language StandaloneKindSignatures #-}
{-# language TypeFamilies #-}
{-# language UndecidableInstances #-}
module Rel8.Column.NonEmpty
( HNonEmpty, AHNonEmpty(..)
)
where
-- base
import Data.Kind ( Type )
import Data.List.NonEmpty ( NonEmpty )
import Data.Type.Equality ( (:~:)( Refl ) )
import Prelude
-- rel8
import Rel8.Aggregate ( Aggregate )
import Rel8.Expr ( Expr )
import Rel8.Kind.Context ( SContext(..), Reifiable( contextSing ) )
import Rel8.Schema.Context ( Col )
import Rel8.Schema.HTable.NonEmpty ( HNonEmptyTable )
import qualified Rel8.Schema.Kind as K
import Rel8.Schema.Name ( Name )
import Rel8.Schema.Reify ( Reify, hreify, hunreify )
import Rel8.Schema.Result ( Result )
import Rel8.Table
( Table, Columns, Congruent, Context, fromColumns, toColumns
, Unreify, reify, unreify
)
import Rel8.Table.NonEmpty ( NonEmptyTable( NonEmptyTable ) )
import Rel8.Table.Recontextualize ( Recontextualize )
import Rel8.Table.Unreify ( Unreifiability(..), Unreifiable, unreifiability )
-- | Nest a 'NonEmpty' list within a 'Rel8able'. @HNonEmpty f a@ will produce a
-- 'NonEmptyTable' @a@ in the 'Expr' context, and a 'NonEmpty' @a@ in the
-- 'Result' context.
type HNonEmpty :: K.Context -> Type -> Type
type family HNonEmpty context where
HNonEmpty (Reify context) = AHNonEmpty context
HNonEmpty Aggregate = NonEmptyTable
HNonEmpty Expr = NonEmptyTable
HNonEmpty Name = NonEmptyTable
HNonEmpty Result = NonEmpty
type AHNonEmpty :: K.Context -> Type -> Type
newtype AHNonEmpty context a = AHNonEmpty (HNonEmpty context a)
instance (Reifiable context, Unreifiable a, Table (Reify context) a) =>
Table (Reify context) (AHNonEmpty context a)
where
type Context (AHNonEmpty context a) = Reify context
type Columns (AHNonEmpty context a) = HNonEmptyTable (Columns a)
type Unreify (AHNonEmpty context a) = HNonEmpty context (Unreify a)
fromColumns = sfromColumnsNonEmpty contextSing
toColumns = stoColumnsNonEmpty contextSing
reify _ = sreifyNonEmpty (unreifiability contextSing)
unreify _ = sunreifyNonEmpty (unreifiability contextSing)
instance
( Reifiable context, Reifiable context'
, Unreifiable a, Unreifiable a'
, Recontextualize (Reify context) (Reify context') a a'
)
=> Recontextualize
(Reify context)
(Reify context')
(AHNonEmpty context a)
(AHNonEmpty context' a')
smapNonEmpty :: Congruent a b
=> SContext context
-> (a -> b)
-> (HNonEmptyTable (Columns a) (Col (Context a)) -> HNonEmptyTable (Columns b) (Col (Context b)))
-> AHNonEmpty context a
-> AHNonEmpty context b
smapNonEmpty = \case
SAggregate -> \_ f (AHNonEmpty (NonEmptyTable a)) -> AHNonEmpty (NonEmptyTable (f a))
SExpr -> \_ f (AHNonEmpty (NonEmptyTable a)) -> AHNonEmpty (NonEmptyTable (f a))
SResult -> \f _ (AHNonEmpty as) -> AHNonEmpty (fmap f as)
SName -> \_ f (AHNonEmpty (NonEmptyTable a)) -> AHNonEmpty (NonEmptyTable (f a))
SReify context -> \f g (AHNonEmpty as) -> AHNonEmpty (smapNonEmpty context f g as)
sfromColumnsNonEmpty :: Table (Reify context) a
=> SContext context
-> HNonEmptyTable (Columns a) (Col (Reify context))
-> AHNonEmpty context a
sfromColumnsNonEmpty = \case
SAggregate -> AHNonEmpty . NonEmptyTable
SExpr -> AHNonEmpty . NonEmptyTable
SResult ->
AHNonEmpty . fmap (fromColumns . hreify) . fromColumns . hunreify
SName -> AHNonEmpty . NonEmptyTable
SReify context ->
AHNonEmpty .
smapNonEmpty context (fromColumns . hreify) hreify .
sfromColumnsNonEmpty context .
hunreify
stoColumnsNonEmpty :: Table (Reify context) a
=> SContext context
-> AHNonEmpty context a
-> HNonEmptyTable (Columns a) (Col (Reify context))
stoColumnsNonEmpty = \case
SAggregate -> \(AHNonEmpty (NonEmptyTable a)) -> a
SExpr -> \(AHNonEmpty (NonEmptyTable a)) -> a
SResult ->
hreify . toColumns . fmap (hunreify . toColumns) . (\(AHNonEmpty a) -> a)
SName -> \(AHNonEmpty (NonEmptyTable a)) -> a
SReify context ->
hreify .
stoColumnsNonEmpty context .
smapNonEmpty context (hunreify . toColumns) hunreify .
(\(AHNonEmpty a) -> a)
sreifyNonEmpty :: Table (Reify context) a
=> Unreifiability context a
-> HNonEmpty context (Unreify a)
-> AHNonEmpty context a
sreifyNonEmpty = \case
UResult -> AHNonEmpty . fmap (reify Refl)
Unreifiability context ->
smapNonEmpty context (reify Refl) hreify .
AHNonEmpty
sunreifyNonEmpty :: Table (Reify context) a
=> Unreifiability context a
-> AHNonEmpty context a
-> HNonEmpty context (Unreify a)
sunreifyNonEmpty = \case
UResult -> fmap (unreify Refl) . (\(AHNonEmpty a) -> a)
Unreifiability context ->
(\(AHNonEmpty a) -> a) .
smapNonEmpty context (unreify Refl) hunreify