如何解决我的GADT中的歧义

Bra*_*gle 9 dsl haskell types gadt

我有两个GADT用于建模SQL EDSL.为了让客户端面对api干净简单,我想OverloadedStrings用来将字符串文字转换为Column Selection.

因此,您只需输入即可

select ["a", "b"] $ from tbl
Run Code Online (Sandbox Code Playgroud)

代替

select [Column "a", Column "b"] $ from tbl
Run Code Online (Sandbox Code Playgroud)

问题是select允许Column Selections和Reductions允许执行聚合的查询.

mean :: Column Selection -> Column Reduction

select :: [Column a] -> Query b -> Query Selection
select [mean "a"] $ from tbl
Run Code Online (Sandbox Code Playgroud)

因此,在这种情况下,字符串是模糊的[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
Run Code Online (Sandbox Code Playgroud)

我也想提出以下签名失败Select/ Update:

[Column Selection] -> Query Reduction -> Query Selection
Run Code Online (Sandbox Code Playgroud)

但那是另外一种蠕虫......

use*_*038 6

编译器是正确的,给你一个暧昧的错误类型Select ["a"]-的IsString (Column Selection)情况下可以选择只有一个先验的说法Column是已知的Selection.这正是预期的行为.

你想要的是以下内容:

instance (x ~ Selection) => IsString (Column x) where
    fromString = Column 
Run Code Online (Sandbox Code Playgroud)

这将允许编译器推断"x" :: Column _必须实际上"x" :: Column Selection,而不是要求它.

Select [mean "a"]是一种完全不同的情况 - 因为mean :: Column Selection -> Column Reduction,在实例选择发生之前,编译器知道"a" :: Column Selection,因为mean强制类型就是这种情况.