データ型の不変条件のエンコードに多くの時間を費やしましたが、現在、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 で不変式を再実装することです。