Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 具有无标记终结符的静态不变量 TL;DR使用无标记编码时,如何对GADT可能使用的静态不变量进行编码?_Sql_Haskell_Types_Dsl - Fatal编程技术网

Sql 具有无标记终结符的静态不变量 TL;DR使用无标记编码时,如何对GADT可能使用的静态不变量进行编码?

Sql 具有无标记终结符的静态不变量 TL;DR使用无标记编码时,如何对GADT可能使用的静态不变量进行编码?,sql,haskell,types,dsl,Sql,Haskell,Types,Dsl,我正在一种类似SQL的语言的基础上构建一个dsl,目标是完善一些粗糙的边缘、类型安全性和较小的查询优化 在我的第一个过程中,我使用GADT强制执行目标语言将执行的几个限制,但在大多数情况下,输出是垃圾。即select语句中混合长度的列,如 select mean x, x by date, time from tbl 我通过将列标记为选择(向量)或缩减(标量)来防止这些混合选择,因此编译器可以静态地防止这些操作。然而,我从未想过如何防止从groupby中进行选择 下一个需要改进的特性是将类型检

我正在一种类似SQL的语言的基础上构建一个dsl,目标是完善一些粗糙的边缘、类型安全性和较小的查询优化

在我的第一个过程中,我使用GADT强制执行目标语言将执行的几个限制,但在大多数情况下,输出是垃圾。即select语句中混合长度的列,如

select mean x, x by date, time from tbl
我通过将列标记为选择(向量)或缩减(标量)来防止这些混合选择,因此编译器可以静态地防止这些操作。然而,我从未想过如何防止从groupby中进行选择

下一个需要改进的特性是将类型检查添加到列算术运算中,我的第一个坏主意是添加另一个幻影类型来携带列类型。这不起作用,因为它会破坏我的模式类型,并且我无法再选择混合类型的列。这让我认为,无标记地嵌入列可能是合适的,因为我可以根据上下文获得适当的表示(类型、大小等)。缺点是,这似乎会将我想要编码的所有不变量推迟到运行时。为了说明这一点,这里是GADT和无标记方法中
add
的粗略伪代码

-- | GADT
add :: Column ty s1 -> Column ty s2
add a b = BinExpr Add a b

-- | Tagless
add :: Column c => c -> c -> c
add a b | (a :: ColType) == (b :: ColType) = binexpr Add a b
        | TypeMismatch a b
GADT方法的另一个好处是能够指定
numty=>…
,以防止在字符串列上添加内容。这类问题似乎会在我的所有代码中传播,因为我现在必须推迟运行时检查,以确保防止
选择大小不一的
仅处理
查询选择
。所以我的问题是:在使用无标记样式的灵活性时,我是否能够以某种方式保留GADT的静态保证

我当前的GADT

{-# LANGUAGE
    GADTs
  , DataKinds
  , TypeFamilies #-}

-- Kinds

-- | State Tags
--   These constructors are promoted to the kind level to be used as 
--   phantom types to enforce static query invariants. For instance
--   these are strategically used to prevent selecting from a Groupby
--   or preventing selection of mixlengthed columns

data Sz = Selection | Reduction deriving Show

--------------------------------------------------------------------
-- Schema 

data Schema = Schema { 
    name :: Maybe String, 
    spec :: [Column Selection] 
} deriving Eq

--------------------------------------------------------------------
-- Column Datatype

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

type family ColOp (a :: Sz) (b :: Sz) where
    -- | If both sides a scalar then output
    --   is still a scalar, otherwise return
    --   a vector, as we can perform the op
    --   elemwise or brodcast a scalar across
    --   the vector
    ColOp Reduction Reduction = Reduction
    ColOp a         b         = Selection 

--------------------------------------------------------------------
-- Query types

class Tabular repr where
    meta  ::  repr (a :: Sz) -> Schema

data Query (a :: Sz) where
    Table  :: Schema -> Query Selection
    Select :: (Tabular t, Show (t b)) => [Column a] -> t b -> Query Selection
    Where  :: (Tabular t, Show (t Selection)) => [Column Selection] -> t Selection -> Query Selection
    Group  :: (Tabular t, Show (t Selection)) => [Column Selection] -> t Selection -> Query Reduction
无标记列原型

{-# language FlexibleInstances #-}

data Sz = Selection | Reduction 
    deriving Show

data ColType 
    = Int | Float | String | Bool 
    | TypeMismatch ColType ColType 
    deriving (Show, Eq)

data BinOp = Add  | Mul
data AggOp = Mean | Count

-- Tagless AST
class Show repr => Column repr where
    column  :: String -> ColType -> repr
    assign  :: String -> repr    -> repr
    binExpr :: BinOp  -> repr    -> repr  -> repr
    aggExpr :: AggOp  -> repr    -> repr

-- Show Instances
instance Show BinOp where
    show Add = " + "
    show Mul = " * "

instance Show AggOp where 
    show Mean  = "mean "
    show Count = "count "

-- I Would like to bring these into the type level (ie performed statically)
opSz :: Sz -> Sz -> Sz
opSz Reduction Reduction = Reduction
opSz a         b         = Selection

typeCheck :: ColType -> ColType -> ColType 
typeCheck a b | a == b = a
              | otherwise = TypeMismatch a b

-- Tagless Interpreters
-- | Stringify
instance Column ([Char]) where 
    column  s t   = s
    assign  s c   = s ++ ": " ++ show c
    binExpr o l r = l ++ show o ++ r
    aggExpr op l  = show op ++ l

-- | Column Size
instance Column Sz where 
    column  s t   = Selection
    assign  s c   = c :: Sz
    binExpr o l r = opSz l r
    aggExpr op l  = Reduction

-- | Column Type
instance Column ColType where 
    column s t    = t
    assign s c    = c :: ColType
    binExpr o l r = typeCheck l r
    aggExpr o l   = l :: ColType

add :: Column c => c -> c -> c
add l r = binExpr Add l r

columns :: Column c => [c]
columns = [ column "a" Float
          , column "b" Int
          , column "c" String ]

a :: Column c => c
a = columns !! 0

b :: Column c => c
b = columns !! 1

-- add a b :: ColType => TypeMismatch Float Int
Edit:我可以通过向类中添加类型参数来获得类似的行为

class Column repr where 
    column  :: String -> repr Selection
    assign  :: String -> repr (a :: Sz) -> repr (a :: Sz)
    binExpr :: BinOp  -> repr (a :: Sz) -> repr (b :: Sz) -> repr (OpSz a b)
    aggExpr :: AggOp  -> repr Selection -> repr Reduction

但我仍然很好奇如何定义ast的解释器,将
ColType
带到类型级别,这样我就可以定义
add::ct->ct->ct
所以
adda::(C字符串)b:(C Int)
首先,在Haskell中正确地键入数据库似乎相当痛苦。它不太适合Haskell的类型系统。其次,我有限的经验表明,GADT比无标记的最终编码更容易思考。即使您想要后者,也可以更容易地从前者和transform.Oleg开始。基本上,将GADT构造函数模拟为类型类的方法,包括类型参数。我不确定为什么
GADT被允许是
Sz->*
类型,但是
类对类型进行分类
*
。我当然可以这样做(参见编辑)。不过,我想我想要的是一个无标记ast的解释器,它可以在方便的时候将列类型(Int、Float等)提升到类型级别,这样我就可以用签名定义add,比如
add::CT->CT->CT