【发布时间】:2016-04-08 16:16:44
【问题描述】:
我花了很多时间在我的数据类型中编码不变量,现在我正在努力通过 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
据我所知,这似乎将类型安全抛到了窗外。从本质上讲,任何交给 Haskell 的 C 都将被假定为那种类型,这完全否定了我在 Haskell 中编写 dsl 的原因。有什么方法可以让我获得使用 StablePtr 的好处并保持类型安全?我想要的最后一件事是在 C 中重新实现不变量。
【问题讨论】:
-
C 可能没有足够强大的类型系统来检查 DSL 的任何部分。也许 c++ 模板可以做到这一点.. 但那是一场噩梦。我认为你必须接受函数 could 在 C 端被错误地调用,并在运行时在 Haskell 端检查它是否正确。当然,您仍然可以在运行时获取类型信息(例如使用
Typeable),因此您仍然可以使用类型良好的 Haskell 函数(在确保来自 C 的输入类型正确之后)。
标签: haskell types ffi type-safety opaque-pointers