packages feed

sqel-0.0.1.0: lib/Sqel/Product.hs

module Sqel.Product where

import Generics.SOP.GGP (GCode, GDatatypeInfoOf)
import Sqel.Comp (CompColumn (compColumn), CompName, MetaFor, ProductFields)
import Sqel.Data.Dd (
  Comp (Prod),
  CompInc (Nest),
  Dd (Dd),
  DdInc (DdNest),
  DdK (DdK),
  DdSort (DdProd),
  DdStruct (DdComp),
  DdType,
  ProdType (Reg),
  Struct (Comp),
  )
import Sqel.Data.Mods (pattern NoMods, NoMods)
import Sqel.Data.Sel (MkTSel (mkTSel), Sel (SelAuto), SelW (SelWAuto))
import Sqel.Names.Rename (Rename (rename))
import Sqel.Names.Set (SetName)

class DdType s ~ a => ProductSel sel a arg s | sel a arg -> s where
  prodSel :: arg -> Dd s

instance (
    MkTSel sel,
    fields ~ ProductFields (GDatatypeInfoOf a) (GCode a),
    meta ~ MetaFor "product type" ('ShowType a) "prod",
    CompColumn meta fields a arg s
  ) => ProductSel sel a arg ('DdK 'SelAuto NoMods a ('Comp sel ('Prod 'Reg) 'Nest s)) where
    prodSel arg =
      Dd SelWAuto NoMods (DdComp mkTSel DdProd DdNest (compColumn @meta @fields @a arg))

class DdType s ~ a => Product a arg s | a arg -> s where
  prod :: arg -> Dd s

instance (
    CompName a sel,
    ProductSel sel a arg s
  ) => Product a arg s where
    prod =
      prodSel @sel @a

prodAs ::
  ∀ (name :: Symbol) (a :: Type) (s :: DdK) (arg :: Type) .
  Product a arg s =>
  Rename s (SetName s name) =>
  arg ->
  Dd (SetName s name)
prodAs =
  rename . prod @_ @_ @s