Haskell到C - 自定义数据类型

时间:2014-04-23 14:07:55

标签: c haskell types

我有以下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.

1 个答案:

答案 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}}实例也可以正常工作。