{-# LANGUAGE TemplateHaskell #-}
module Preql.Wire.Tuples where
import Language.Haskell.TH
alphabet :: [String]
alphabet = cycle (map (:"") ['a'..'z'])
deriveFromSqlTuple :: Int -> Q [Dec]
deriveFromSqlTuple n = do
names <- traverse newName (take n alphabet)
Just classN <- lookupTypeName "FromSql"
Just methodN <- lookupValueName "fromSql"
let
context = [ ConT classN `AppT` VarT n | n <- names ]
instanceHead = ConT classN `AppT` foldl AppT (TupleT n) (map VarT names)
method = ValD
(VarP methodN)
(NormalB (foldl
(\row field -> InfixE (Just row) (VarE '(<*>)) (Just field))
(VarE 'pure `AppE` ConE (tupleDataName n))
(replicate n (VarE methodN))))
[]
return [InstanceD Nothing context instanceHead [method]]
deriveToSqlTuple :: Int -> Q [Dec]
deriveToSqlTuple n = do
names <- traverse newName (take n alphabet)
Just classN <- lookupTypeName "ToSql"
Just fieldN <- lookupTypeName "ToSqlField"
Just toSql <- lookupValueName "toSql"
Just runFieldEncoder <- lookupValueName "runFieldEncoder"
Just toSqlField <- lookupValueName "toSqlField"
let
context = [ ConT fieldN `AppT` VarT n | n <- names ]
instanceHead = ConT classN `AppT` foldl AppT (TupleT n) (map VarT names)
method = FunD toSql
[Clause
[TupP (map VarP names)]
(NormalB (ListE [ VarE runFieldEncoder `AppE` VarE toSqlField `AppE` VarE n | n <- names ]))
[]]
return [InstanceD Nothing context instanceHead [method]]