rel8-1.1.0.0: src/Rel8/Schema/HTable/Label.hs
{-# language DataKinds #-}
{-# language RankNTypes #-}
{-# language RecordWildCards #-}
{-# language ScopedTypeVariables #-}
{-# language StandaloneKindSignatures #-}
{-# language TypeApplications #-}
{-# language TypeFamilies #-}
module Rel8.Schema.HTable.Label
( HLabel, hlabel, hrelabel, hunlabel
, hproject
)
where
-- base
import Data.Kind ( Type )
import Data.Proxy ( Proxy( Proxy ) )
import GHC.TypeLits ( KnownSymbol, Symbol, symbolVal )
import Prelude
-- rel8
import Rel8.Schema.HTable
( HTable, HConstrainTable, HField
, htabulate, hfield, htraverse, hdicts, hspecs
)
import qualified Rel8.Schema.Kind as K
import Rel8.Schema.Spec ( Spec(..) )
type HLabel :: Symbol -> K.HTable -> K.HTable
newtype HLabel label table context = HLabel (table context)
type HLabelField :: Symbol -> K.HTable -> Type -> Type
newtype HLabelField label table a = HLabelField (HField table a)
instance (HTable table, KnownSymbol label) => HTable (HLabel label table) where
type HField (HLabel label table) = HLabelField label table
type HConstrainTable (HLabel label table) constraint =
HConstrainTable table constraint
hfield (HLabel a) (HLabelField field) = hfield a field
htabulate f = HLabel (htabulate (f . HLabelField))
htraverse f (HLabel a) = HLabel <$> htraverse f a
hdicts = HLabel (hdicts @table)
hspecs = HLabel $ htabulate $ \field -> case hfield (hspecs @table) field of
Spec {..} -> Spec {labels = symbolVal (Proxy @label) : labels, ..}
{-# INLINABLE hspecs #-}
hlabel :: forall label t context. t context -> HLabel label t context
hlabel = HLabel
{-# INLINABLE hlabel #-}
hrelabel :: forall label' label t context. HLabel label t context -> HLabel label' t context
hrelabel = hlabel . hunlabel
{-# INLINABLE hrelabel #-}
hunlabel :: forall label t context. HLabel label t context -> t context
hunlabel (HLabel a) = a
{-# INLINABLE hunlabel #-}
hproject :: ()
=> (forall ctx. t ctx -> t' ctx)
-> HLabel label t context -> HLabel label t' context
hproject f (HLabel a) = HLabel (f a)