我有两个用于模拟SQL EDSL的GADT。为了使面向API的客户端保持整洁和简单,我想使用OverloadedStrings
将字符串文字转换为Column Selection
。
因此,您只需键入
select ["a", "b"] $ from tbl
代替
select [Column "a", Column "b"] $ from tbl
问题是select允许Column Selection
s和Reduction
s都允许执行聚合的查询。
mean :: Column Selection -> Column Reduction
select :: [Column a] -> Query b -> Query Selection
select [mean "a"] $ from tbl
因此在这种情况下字符串是不明确的[Column a]
。但是select [mean "a"] $ from tbl
有效,因为mean
它提供了必要的上下文来推断字符串文字是“列选择”。
谁能推荐摆脱这种混乱的出路?
我下面的当前代码(忽略了无关的实例)
{-# LANGUAGE
GADTs
, RankNTypes
, DataKinds
, TypeFamilies
, FlexibleContexts
, FlexibleInstances
, OverloadedStrings #-}
data Sz = Selection | Reduction deriving Show
data Schema = Schema{name :: Maybe String, spec :: [Column Selection]}
type family ColOp (a :: Sz) (b :: Sz) where
ColOp Selection Selection = Selection
ColOp Selection Reduction = Selection
ColOp Reduction Selection = Selection
ColOp Reduction Reduction = Reduction
data Column (a :: Sz) where
Column :: String -> Column Selection
Assign :: String -> Column a -> Column a
FKey :: String -> Schema -> Column Selection
BinExpr :: BinOp -> Column a -> Column b -> Column (ColOp a b)
LogExpr :: LogOp -> Column a -> Column b -> Column Selection
AggExpr :: AggOp -> Column Selection -> Column Reduction
instance IsString (Column Selection) where
fromString s = Column s
data Query (a :: Sz) where
Table :: Schema -> Query Selection
Select :: [Column a] -> Query b -> Query Selection
Update :: [Column a] -> Query b -> Query Selection
Where :: [Column Selection] -> Query Selection -> Query Selection
Group :: [Column Selection] -> Query Selection -> Query Reduction
我也想提出以下签名失败Select
/ Update
:
[Column Selection] -> Query Reduction -> Query Selection
但这就是蠕虫的另一罐……
编译器是正确的,将为您带来模棱两可的类型错误Select ["a"]
-仅当已知先验参数为时,才IsString (Column Selection)
可以选择实例。这正是预期的行为。Column
Selection
您想要的是以下内容:
instance (x ~ Selection) => IsString (Column x) where
fromString = Column
这将允许编译器推断"x" :: Column _
必须实际为"x" :: Column Selection
,而不是要求。
Select [mean "a"]
这是完全不同的情况-因为mean :: Column Selection -> Column Reduction
,编译器在实例选择发生之前就知道"a" :: Column Selection
,因为mean
强制类型是这种情况。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句