morphismtech / squeal

Squeal, a deep embedding of SQL in Haskell
362 stars 32 forks source link

Combinators for hand rolling `ToPG` for `PGenum`s and `PGcomposite`s #312

Closed echatav closed 2 years ago

echatav commented 2 years ago

Squeal had combinators for hand rolling FromPG instances for PGenums and PGcomposites. This PR adds combinators for hand rolling ToPG instances. To do this it loosens the EncodeParams type to be polykinded newtype EncodeParams (db :: SchemasType) (tys :: [k]) (x :: Type). The type variable tys can be a list of any kind, where before it was [NullType]. We need to instantiate it for one other list, RowType. Then we define the following combinator to use these RowTyped parameter encodings to define toPG methods.

rowParam
  :: forall db row x. (PG x ~ 'PGcomposite row, SOP.All (OidOfField db) row)
  => EncodeParams db row x
  -> x -> ReaderT (SOP.K LibPQ.Connection db) IO Encoding

To construct RowTyped parameter encodings, we can use some old combinators like nilParams and appendParams but the rest like .*, *. and genericParams will be useless since they don't address field names. So similar combinators .#, #. and genericRowParams are provided.

Additionally, a combinator is provided to define toPG for PGenums.

enumParam
  :: forall db labels x. (PG x ~ 'PGenum labels, SOP.All KnownSymbol labels)
  => (x -> SOP.NS PGlabel labels)
  -> x -> ReaderT (SOP.K LibPQ.Connection db) IO Encoding
echatav commented 2 years ago

Is #. necessary or can we use scrap-your-nils?

echatav commented 2 years ago

Is #. necessary or can we use scrap-your-nils?

No because the inference constraint on Aliasable, GHC explains the problem:

>     • Illegal instance declaration for
>         ‘Aliasable fld (x -> x0) (EncodeParams db '[fld ::: ty] x)’
>         The liberal coverage condition fails in class ‘Aliasable’
>           for functional dependency: ‘aliased -> expression’
>         Reason: lhs type ‘EncodeParams db '[fld ::: ty] x’
>           does not determine rhs type ‘x -> x0’
>         Un-determined variable: x0