我有以下 Haskell 数据类型:
data RegExp sy = Empty
| Epsilon
| Literal sy
| Or (RegExp sy) (RegExp sy)
| Then (RegExp sy) (RegExp sy)
| Star (RegExp sy)
deriving (Read, Eq)
我需要从 C 调用它,我想知道是否有人对此有任何经验?我已经用本教程中的简单数据类型完成了它:http://www.haskell.org/haskellwiki/Calling_Haskell_from_C但我不确定该怎么做,因为我有自己定义的数据类型。
显示返回一个字符串,如下所示:
*Language.HaLex.RegExp> let f = (Or a a)
*Language.HaLex.RegExp> :t f
f :: RegExp Char
*Language.HaLex.RegExp> show f
"'a'+'a'"
*Language.HaLex.RegExp> :t show f
show f :: String
但是当我有以下内容时:
simplifyRegExp_hs :: CString -> CString
simplifyRegExp_hs = simplifyRegExp
foreign export ccall simplifyRegExp_hs :: CString -> CString
出现以下错误:
Simplify.hs:317:21:
Couldn't match type `RegExp t0'
with `GHC.Ptr.Ptr Foreign.C.Types.CChar'
Expected type: CString -> CString
Actual type: RegExp t0 -> RegExp t0
In the expression: simplifyRegExp
In an equation for `simplifyRegExp_hs':
simplifyRegExp_hs = simplifyRegExp
Simplify.hs:319:1:
Illegal foreign declaration: requires via-C, llvm (-fllvm) or native code generation (-fvia-C)
When checking declaration:
foreign export ccall "simplifyRegExp_hs" simplifyRegExp_hs
:: CString -> CString
Failed, modules loaded: none.
最佳答案
当 simplifyRegExp
的类型为 RegExp a -> RegExp a
时,你向编译器声明 simplifyRegExp
的类型为 CString -> CString
。您需要先编写实际具有 CString -> CString
类型的函数。这意味着为您的 RegExp
类型提供一个 Read
实例以与 show 实例一起使用。完成后,您可以执行以下操作:
simplifyRegExp_hs :: CString -> IO CString
simplifyRegExp_hs cs = do s <- peekCString cs
let reg = read s :: RegExp <element type>
newCString (show reg)
如果为您的类型编写Read
实例并不容易,您需要将数据类型编码为 C 结构,并提供从您的 Haskell 类型到 Haskell 中的 C 结构的转换.一般来说,这是更好的解决方案,因为您不必不必要地处理解析器,但如果您的示例足够简单,Read
实例也可以工作。
关于c - Haskell 到 C - 自定义数据类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23246893/