如何仅将类型(种类?)约束到产品类型

时间:2012-04-05 15:22:29

标签: haskell

我正在研究使用monad comprehensions来表示SQL查询,并生成适当的SQL。乍一看,这不是问题,似乎很合适。但我必须限制类型,这可以形成monad只有产品,没有总和,我想不出这种约束的方法。

我想使用类型检查器来确保只能使用SQL中可表示的类型。

我想,我可以使用模板haskell来派生正确的实例,如果类型不合适则拒绝派生,但我更喜欢在类型级别完成。由于我的无知,我引入错误的机会较少。

我怎么能这样做?如果是,请您推荐一些阅读和/或代码示例。

编辑:谢谢,我有一些很好的路径可以关注,需要更多的阅读:)这是一个漫长的周末。

1 个答案:

答案 0 :(得分:8)

不幸的是,这实际上是不可能的:Monad必须是完全多态的。这与你无法使Set成为monad(Ord约束)的原因相同。

如果只处理结果类型符合约束,那么你可能有runSQL :: (Product a) => SQL a -> IO a或类似的。在这种情况下,只需使用模板Haskell派生适当的实例即可,或者使用新的GHC Generics;普通的Haskell无法确定某个类型是否仅由产品组成。

但我怀疑你需要访问monadic计算的整个结构,将其转换为SQL。不幸的是,monad对此没有很好的装备,因为它们与任意Haskell函数一起插入,你无法“查看”内部。 Arrows更接近,让你做更多静态分析,但仍然有那个讨厌的arr,再次让你潜入任意Haskell函数。

做这样的事情最可行的选择可能是编写一个Template Haskell接合器来解析你想要的语法;您可以说$(sql [| [ (a,b) | a <- table1, b <- table2 |])并让sql在编译时将AST转换为相应的SQL如果该语法太难看,您可以使用带有haskell-src-meta的quasiquoter,它看起来像{ {1}}。

您可能也对generalised arrows扩展程序感兴趣,虽然它可能对您的目的而言过于苛刻(并且过于实验性)。