rel8-1.0.0.0: src/Rel8/Schema/HTable/Vectorize.hs
{-# language AllowAmbiguousTypes #-}
{-# language ConstraintKinds #-}
{-# language DataKinds #-}
{-# language DeriveAnyClass #-}
{-# language DeriveGeneric #-}
{-# language DerivingStrategies #-}
{-# language FlexibleContexts #-}
{-# language FlexibleInstances #-}
{-# language GADTs #-}
{-# language LambdaCase #-}
{-# language MultiParamTypeClasses #-}
{-# language NamedFieldPuns #-}
{-# language QuantifiedConstraints #-}
{-# language RankNTypes #-}
{-# language RecordWildCards #-}
{-# language ScopedTypeVariables #-}
{-# language StandaloneKindSignatures #-}
{-# language TypeApplications #-}
{-# language TypeFamilies #-}
{-# language UndecidableInstances #-}
module Rel8.Schema.HTable.Vectorize
( HVectorize
, hvectorize, hunvectorize
, happend, hempty
)
where
-- base
import Data.Kind ( Type )
import Data.List.NonEmpty ( NonEmpty )
import Prelude
-- rel8
import Rel8.Schema.Context.Label ( HLabelable, hlabeler, hunlabeler )
import Rel8.Schema.Dict ( Dict( Dict ) )
import qualified Rel8.Schema.Kind as K
import Rel8.Schema.HTable
( HTable
, hfield, htabulate, htabulateA, hspecs
)
import Rel8.Schema.Null ( Unnullify, NotNull, Nullity( NotNull ) )
import Rel8.Schema.Spec ( Spec( Spec ), SSpec(..) )
import Rel8.Type.Array ( listTypeInformation, nonEmptyTypeInformation )
import Rel8.Type.Information ( TypeInformation )
-- semialign
import Data.Zip ( Unzip, Zip, Zippy(..) )
import Rel8.FCF
import Rel8.Schema.HTable.MapTable
import GHC.Generics (Generic)
class Vector list where
listNotNull :: proxy a -> Dict NotNull (list a)
vectorTypeInformation :: ()
=> Nullity a
-> TypeInformation (Unnullify a)
-> TypeInformation (list a)
instance Vector [] where
listNotNull _ = Dict
vectorTypeInformation = listTypeInformation
instance Vector NonEmpty where
listNotNull _ = Dict
vectorTypeInformation = nonEmptyTypeInformation
type HVectorize :: (Type -> Type) -> K.HTable -> K.HTable
newtype HVectorize list table context = HVectorize (HMapTable (Vectorize list) table context)
deriving stock Generic
deriving anyclass HTable
data Vectorize :: (Type -> Type) -> Spec -> Exp Spec
type instance Eval (Vectorize list ('Spec labels a)) = 'Spec labels (list a)
instance Vector list => MapSpec (Vectorize list) where
mapInfo = \case
SSpec {..} -> case listNotNull @list nullity of
Dict -> SSpec
{ nullity = NotNull
, info = vectorTypeInformation nullity info
, ..
}
hvectorize :: (HTable t, Unzip f, Vector list)
=> (forall labels a. ()
=> SSpec ('Spec labels a)
-> f (context ('Spec labels a))
-> context' ('Spec labels (list a)))
-> f (t context)
-> HVectorize list t context'
hvectorize vectorizer as = HVectorize $ htabulate $ \(HMapTableField field) ->
case hfield hspecs field of
spec@SSpec {} -> vectorizer spec (fmap (`hfield` field) as)
{-# INLINABLE hvectorize #-}
hunvectorize :: (HTable t, Zip f, Vector list)
=> (forall labels a. ()
=> SSpec ('Spec labels a)
-> context ('Spec labels (list a))
-> f (context' ('Spec labels a)))
-> HVectorize list t context
-> f (t context')
hunvectorize unvectorizer (HVectorize table) =
getZippy $ htabulateA $ \field -> case hfield hspecs field of
spec@SSpec{} -> case hfield table (HMapTableField field) of
a -> Zippy (unvectorizer spec a)
{-# INLINABLE hunvectorize #-}
happend :: (HTable t, Vector list) =>
( forall labels a. ()
=> Nullity a
-> TypeInformation (Unnullify a)
-> context ('Spec labels (list a))
-> context ('Spec labels (list a))
-> context ('Spec labels (list a))
)
-> HVectorize list t context
-> HVectorize list t context
-> HVectorize list t context
happend append (HVectorize as) (HVectorize bs) = HVectorize $
htabulate $ \field@(HMapTableField j) -> case (hfield as field, hfield bs field) of
(a, b) -> case hfield hspecs j of
SSpec {nullity, info} -> append nullity info a b
hempty :: HTable t =>
( forall labels a. ()
=> Nullity a
-> TypeInformation (Unnullify a)
-> context ('Spec labels [a])
)
-> HVectorize [] t context
hempty empty = HVectorize $ htabulate $ \(HMapTableField field) -> case hfield hspecs field of
SSpec {nullity, info} -> empty nullity info
instance HLabelable g => HLabelable (Precompose (Vectorize list) g) where
hlabeler = Precompose . hlabeler . precomposed
hunlabeler = Precompose . hunlabeler . precomposed