2014-04-23 46 views
1

我有以下的Haskell數據類型:哈斯克爾到C - 自定義的數據類型

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

http://www.haskell.org/haskellwiki/FFI_Introduction – user2485710

回答

4

你」重新向編譯器聲稱simplifyRegExp有類型CString -> CString當它有類型RegExp a -> RegExp a。您需要先編寫實際具有類型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實例也可以工作。