我有两个用于建模SQL EDSL的GADT。为了让客户端面对api干净简单,我想使用OverloadedStrings
将字符串文字转换为Column Selection
。
因此您只需输入
即可select ["a", "b"] $ from tbl
而不是
select [Column "a", Column "b"] $ from tbl
问题是select允许Column Selection
和Reduction
允许执行聚合的查询。
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
但那是另一种蠕虫......
答案 0 :(得分:6)
编译器是正确的,为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
的类型迫使它成为prepared a avia model schema for test.
Ticket(uuid: Long, flyCompany: FlyCompany, sitNumber: Int, user: User, date: String, ... )
User(uuid: Long, firstName: String, lastName: String, ... )
案子。