我花了很多时间在我的数据类型中编码不变量,现在我正在努力通过 FFI 将我的库暴露给 C。我没有跨语言障碍编组数据结构,而是简单地使用不透明的指针来允许 C 构建一个 AST,然后在eval
Haskell 上只需要将一个字符串编组到 C。
这是一些更有启发性的代码。
-- excerpt from Query.hs
data Sz = Selection | Reduction deriving Show
-- Column Datatype
data Column (a :: Sz) where
Column :: String -> Column Selection
BinExpr :: BinOp -> Column a -> Column b -> Column (OpSz a b)
AggExpr :: AggOp -> Column Selection -> Column Reduction
type family OpSz (a :: Sz) (b :: Sz) where
OpSz Selection Selection = Selection
OpSz Selection Reduction = Selection
OpSz Reduction Selection = Selection
OpSz Reduction Reduction = Reduction
data Query (a :: Sz) where
... etc
-- excerpt from Export.hs
foreign export ccall "selection"
select :: StablePtr [Column a] -> StablePtr (Query b) -> IO (StablePtr (Query Selection))
foreign export ccall
add :: StablePtr (Column a) -> StablePtr (Column b) -> IO (StablePtr (Column (OpSz a b)))
foreign export ccall
mul :: StablePtr (Column a) -> StablePtr (Column b) -> IO (StablePtr (Column (OpSz a b)))
foreign export ccall
eval :: StablePtr (Query Selection) -> IO CString
然而,据我所知,这似乎将类型安全抛到了窗外。基本上任何 C 交给 Haskell 的东西都会被认为是那种类型,这完全否定了我在 Haskell 中编写 dsl 的原因。有什么方法可以让我获得使用 StablePtr 的好处并保持类型安全?我想要的最后一件事是在 C 中重新实现不变量。