我有以下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.
答案 0 :(得分:4)
当simplifyRegExp
类型为CString -> CString
时,您声称RegExp a -> RegExp a
具有CString -> CString
类型的编译器。您需要首先编写实际具有类型Read
的函数。这意味着为您的RegExp
类型提供simplifyRegExp_hs :: CString -> IO CString
simplifyRegExp_hs cs = do s <- peekCString cs
let reg = read s :: RegExp <element type>
newCString (show reg)
实例以与show实例一起使用。完成后,您可以执行以下操作:
Read
如果为您的类型编写Read
实例并不容易,则需要将数据类型封送到C结构中,并提供从Haskell类型到Haskell中的C结构的转换。这通常是更好的解决方案,因为您不必不必要地处理解析器,但如果您的示例足够简单,{{1}}实例也可以正常工作。