在不使用 TemplateHaskell 的情况下声明 Opaleye table
Declaring an Opaleye table without using TemplateHaskell
opaleye
basic tutorial 给出了一个关于如何在记录类型和查询中使用用户定义类型的示例:
data Birthday' a b = Birthday { bdName :: a, bdDay :: b }
type Birthday = Birthday' String Day
type BirthdayColumn = Birthday' (Column PGText) (Column PGDate)
birthdayTable :: Table BirthdayColumn BirthdayColumn
birthdayTable = table "birthdayTable"
(pBirthday Birthday { bdName = tableColumn "name"
, bdDay = tableColumn "birthday" })
函数 pBirthday
是使用 TemplateHaskell
:
生成的
$(makeAdaptorAndInstance "pBirthday" ''Birthday')
其中 makeAdaptorAndInstance
是在 Data.Functor.Product.TH
中定义的。
我想避免使用 TemplateHaskell
。 opaleye
教程简单参考了Data.Functor.Product.TH
的文档,只说明了makeAdaptorAndInstance
生成的实例会是:
instance (ProductProfunctor p, Default p a a', Default p b b', Default p c c')
=> Default p (Birthday a b c) (Birthday a' b' c')
和 pBirthday
将具有以下类型:
pBirthday :: ProductProfunctor p =>
Birthday (p a a') (p b b') (p c c') -> p (Birthday a b c) (Birthday a' b' c')
但是我找不到任何关于如何手动填充实现这些功能的信息。
GHC 有一个 -ddump-splices
option 可以查看用 TH 生成的代码。我认为这应该很有用,因为它看起来可能还不错。 (用-ddump-to-file
和-dumpdir
来控制输出位置。)
这是一种写法:
instance (ProductProfunctor p, Default p a a', Default p b b') => Default p (Birthday' a b) (Birthday' a' b') where
def :: p (Birthday' a b) (Birthday' a' b')
def = pBirthday (Birthday def def)
pBirthday :: ProductProfunctor p =>
Birthday' (p a a') (p b b') -> p (Birthday a b) (Birthday a' b')
pBirthday (Birthday pa pb) =
Birthday `rmap` lmap bdName pa **** lmap bdDay pb
-- It generalizes the applicative construct
-- "Birthday <$> pa <*> pb"
opaleye
basic tutorial 给出了一个关于如何在记录类型和查询中使用用户定义类型的示例:
data Birthday' a b = Birthday { bdName :: a, bdDay :: b }
type Birthday = Birthday' String Day
type BirthdayColumn = Birthday' (Column PGText) (Column PGDate)
birthdayTable :: Table BirthdayColumn BirthdayColumn
birthdayTable = table "birthdayTable"
(pBirthday Birthday { bdName = tableColumn "name"
, bdDay = tableColumn "birthday" })
函数 pBirthday
是使用 TemplateHaskell
:
$(makeAdaptorAndInstance "pBirthday" ''Birthday')
其中 makeAdaptorAndInstance
是在 Data.Functor.Product.TH
中定义的。
我想避免使用 TemplateHaskell
。 opaleye
教程简单参考了Data.Functor.Product.TH
的文档,只说明了makeAdaptorAndInstance
生成的实例会是:
instance (ProductProfunctor p, Default p a a', Default p b b', Default p c c')
=> Default p (Birthday a b c) (Birthday a' b' c')
和 pBirthday
将具有以下类型:
pBirthday :: ProductProfunctor p =>
Birthday (p a a') (p b b') (p c c') -> p (Birthday a b c) (Birthday a' b' c')
但是我找不到任何关于如何手动填充实现这些功能的信息。
GHC 有一个 -ddump-splices
option 可以查看用 TH 生成的代码。我认为这应该很有用,因为它看起来可能还不错。 (用-ddump-to-file
和-dumpdir
来控制输出位置。)
这是一种写法:
instance (ProductProfunctor p, Default p a a', Default p b b') => Default p (Birthday' a b) (Birthday' a' b') where
def :: p (Birthday' a b) (Birthday' a' b')
def = pBirthday (Birthday def def)
pBirthday :: ProductProfunctor p =>
Birthday' (p a a') (p b b') -> p (Birthday a b) (Birthday a' b')
pBirthday (Birthday pa pb) =
Birthday `rmap` lmap bdName pa **** lmap bdDay pb
-- It generalizes the applicative construct
-- "Birthday <$> pa <*> pb"