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

dik*_*ini 5 haskell

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

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

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

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

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

ehi*_*ird 8

不幸的是,这实际上是不可能的:Monad必须是完全多态的.这与你不能制作Setmonad(Ord约束)的原因相同.

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

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

做这样的事情最可行的选择可能就是编写一个Template Haskell接合器来解析你想要的语法; 你可以说$(sql [| [ (a,b) | a <- table1, b <- table2 |])并且在sql编译时将AST翻译成相应的SQL如果那个语法太难看了,你可以使用带有haskell-src-meta的quasiquoter,看起来就像[sql| (a, b) | a <- table1, b <- table2 |].

您可能也会对广义箭头扩展感兴趣,尽管它可能对您的目的而言过度杀伤(并且过于实验性).