我已经学习了一些
Haskell编程语言,现在我发现可以从C程序调用Haskell函数.在我的Haskell研究期间,我用Haskell创建了一个单词频率计数器,我想尝试从C程序调用该函数,但是我不知道该怎么做.我在haskell.org上发现了这两个网站:
Foreign C types (Haskell module)
尽管如此,我有点失去使用哪些类型.我的haskell程序是以下功能的管道:
putStr . unlines . map testF . sortedTree
我自己的功能
> testF是testF ::的类型显示a => ([Char],a) – > [字符]
> sortedTree是sortedTree的类型::(Num a,Ord a)=> [Char] – > [([字符],A)]
我确定我需要将每个函数的类型转换为C类型,而不是仅转换调用管道的函数. “主”功能的类型是
fileFreq :: [Char] – > IO()
除此之外,我使用Haskell二进制树,这不是前奏类型.
这是整个Haskell代码:
module WordCounter where import List import Char import Foreign.C.Types data BTree a = Tip | BNode a (BTree a) (BTree a) deriving Show insertFreq x Tip = BNode (x,1) Tip Tip insertFreq x (BNode (q,p) l r) | (map toLower x)==(map toLower q) = BNode (q,p+1) l r | otherwise = BNode (q,p) l (insertFreq x r) tlist :: BTree a -> [a] tlist Tip = [] tlist (BNode x l r) = concat [tlist l,[x],tlist r] sortedTree x = sortBy (\(x,y) (p,q) -> compare q y) (tlist (foldr insertFreq Tip (words x))) testF (x,n) = concat (x : ":" : " \t\t\t " : show n : []) concord = putStr . unlines . map testF . sortedTree fileFreq filename = do { text <- readFile filename; concord text }
有人可以引导我一点吗?
解决方法
您将需要做的是为需要暴露于C的函数创建包装器函数,并从C类型转换为haskell类型.
您还需要启用ForeignFunctionInterface扩展,还可能在包装器函数中处理haskell代码中可能发生的任何异常.
例如,如果您只需要将顶层函数fileFreq公开给C,您可以添加如下功能:
fileFreq_hs :: CString -> IO CInt fileFreq_hs cstr = catch (wrap_fileFreq cstr) (\_ -> return (-1)) where wrap_fileFreq = do str <- peekCString cstr fileFreq str return 0
创建一个函数,将C字符串编组成一个haskell字符串(使用来自Foreign.C.String的函数),调用fileFreq函数并将异常转换为C错误代码(如果异常发生则为-1,否则为0).
那么你需要使用它来导出它
foreign export ccall fileFreq_hs :: CString -> IO CInt
当然你还需要添加:
{-# LANGUAGE ForeignFunctionInterface #-}
在你的模块的顶部.
然后,您可以按照您提供的链接中的说明将其编译为C-stub和头文件,并创建可以使用ghc编译的C文件.
当然可以包装你所拥有的任何功能,你只需要确保处理可能的异常,并组织C类型和haskell类型.
{-# LANGUAGE ForeignFunctionInterface #-} module WordCounter where import List import Char import Foreign.C.Types import Foreign.C.String import Control.Monad data BTree a = Tip | BNode a (BTree a) (BTree a) deriving Show insertFreq x Tip = BNode (x,tlist r] sortedTree :: (Ord t,Num t) => String -> [([Char],t)] sortedTree x = sortBy (\(x,q) -> compare q y) (tlist (foldr insertFreq Tip (words x))) testF :: (Show t) => ([Char],t) -> [Char] testF (x,n) = concat (x : ":" : " \t\t\t " : show n : []) concord = putStr . unlines . map testF . sortedTree fileFreq filename = do { text <- readFile filename; concord text } fileFreq_hs :: CString -> IO CInt fileFreq_hs cstr = catch (wrap_fileFreq cstr) (\_ -> return (-1)) where wrap_fileFreq cstr = do str <- peekCString cstr fileFreq str return 0 foreign export ccall fileFreq_hs :: CString -> IO CInt