packages feed

rel8-1.0.0.0: src/Rel8/Column/These.hs

{-# language DataKinds #-}
{-# language FlexibleContexts #-}
{-# language GADTs #-}
{-# language LambdaCase #-}
{-# language MultiParamTypeClasses #-}
{-# language StandaloneKindSignatures #-}
{-# language TypeFamilies #-}
{-# language UndecidableInstances #-}

module Rel8.Column.These
  ( HThese, AHThese(..)
  )
where

-- base
import Control.Applicative ( liftA2 )
import Data.Bifunctor ( Bifunctor, bimap )
import Data.Kind ( Type )
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.These ( HTheseTable )
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, Context, fromColumns, toColumns
  , Unreify, reify, unreify
  )
import Rel8.Table.Recontextualize ( Recontextualize )
import Rel8.Table.These ( TheseTable )

-- these
import Data.These ( These )


-- | Nest an 'These' value within a 'Rel8able'. @HThese f a b@ will produce a
-- 'TheseTable' @a b@ in the 'Expr' context, and a 'These' @a b@ in the
-- 'Result' context.
type HThese :: K.Context -> Type -> Type -> Type
type family HThese context where
  HThese (Reify context) = AHThese context
  HThese Aggregate = TheseTable
  HThese Expr = TheseTable
  HThese Name = TheseTable
  HThese Result = These


type AHThese :: K.Context -> Type -> Type -> Type
newtype AHThese context a b = AHThese (HThese context a b)


instance Reifiable context => Bifunctor (AHThese context) where
  bimap = sbimapThese contextSing


instance Reifiable context => Functor (AHThese context a) where
  fmap = bimap id


instance (Reifiable context, Table (Reify context) a, Table (Reify context) b)
  => Table (Reify context) (AHThese context a b)
 where
  type Context (AHThese context a b) = Reify context
  type Columns (AHThese context a b) = HTheseTable (Columns a) (Columns b)
  type Unreify (AHThese context a b) = HThese context (Unreify a) (Unreify b)

  fromColumns = sfromColumnsThese contextSing
  toColumns = stoColumnsThese contextSing
  reify proof = liftA2 bimap reify reify proof . AHThese
  unreify proof = (\(AHThese a) -> a) . liftA2 bimap unreify unreify proof


instance
  ( Reifiable context, Reifiable context'
  , Recontextualize (Reify context) (Reify context') a a'
  , Recontextualize (Reify context) (Reify context') b b'
  ) =>
  Recontextualize
    (Reify context)
    (Reify context')
    (AHThese context a b)
    (AHThese context' a' b')


sbimapThese :: ()
  => SContext context
  -> (a -> c)
  -> (b -> d)
  -> AHThese context a b
  -> AHThese context c d
sbimapThese = \case
  SAggregate -> \f g (AHThese a) -> AHThese (bimap f g a)
  SExpr -> \f g (AHThese a) -> AHThese (bimap f g a)
  SResult -> \f g (AHThese a) -> AHThese (bimap f g a)
  SName -> \f g (AHThese a) -> AHThese (bimap f g a)
  SReify context -> \f g (AHThese a) -> AHThese (sbimapThese context f g a)


sfromColumnsThese :: (Table (Reify context) a, Table (Reify context) b)
  => SContext context
  -> HTheseTable (Columns a) (Columns b) (Col (Reify context))
  -> AHThese context a b
sfromColumnsThese = \case
  SAggregate ->
    AHThese .
    bimap (fromColumns . hreify) (fromColumns . hreify) .
    fromColumns .
    hunreify
  SExpr ->
    AHThese .
    bimap (fromColumns . hreify) (fromColumns . hreify) .
    fromColumns .
    hunreify
  SResult ->
    AHThese .
    bimap (fromColumns . hreify) (fromColumns . hreify) .
    fromColumns .
    hunreify
  SName ->
    AHThese .
    bimap (fromColumns . hreify) (fromColumns . hreify) .
    fromColumns .
    hunreify
  SReify context ->
    AHThese .
    sbimapThese context (fromColumns . hreify) (fromColumns . hreify) .
    sfromColumnsThese context .
    hunreify


stoColumnsThese :: (Table (Reify context) a, Table (Reify context) b)
  => SContext context
  -> AHThese context a b
  -> HTheseTable (Columns a) (Columns b) (Col (Reify context))
stoColumnsThese = \case
  SAggregate ->
    hreify .
    toColumns .
    bimap (hunreify . toColumns) (hunreify . toColumns) .
    (\(AHThese a) -> a)
  SExpr ->
    hreify .
    toColumns .
    bimap (hunreify . toColumns) (hunreify . toColumns) .
    (\(AHThese a) -> a)
  SResult ->
    hreify .
    toColumns .
    bimap (hunreify . toColumns) (hunreify . toColumns) .
    (\(AHThese a) -> a)
  SName ->
    hreify .
    toColumns .
    bimap (hunreify . toColumns) (hunreify . toColumns) .
    (\(AHThese a) -> a)
  SReify context ->
    hreify .
    stoColumnsThese context .
    sbimapThese context (hunreify . toColumns) (hunreify . toColumns) .
    (\(AHThese a) -> a)