如何选择合适的Haskell C类型?
我学习了一些 Haskell 编程语言,现在我发现可以从 C 程序调用 Haskell 函数。在我的 Haskell 学习期间,我用 Haskell 创建了一个词频计数器,我想尝试从 C 程序调用该函数,但我不知道该怎么做。我在 haskell.org 上找到了这两个网站:
尽管如此,我'我有点不知道该使用哪种类型。我的 haskell 程序是以下函数的管道:
putStr 。取消行。地图测试F .排序树
其中我自己的函数
- testF 是 testF :: Show a =>; 的类型([Char],a) -> [Char]
- sortedTree 是 sortedTree :: (Num a, Ord a) => 的类型[字符]-> [([Char],a)]
我非常确定我需要将每个函数的类型转换为 C 类型,而不是仅转换调用管道的函数。 “main”函数的类型是
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 }
任何人都可以指导我吗?
I have studied some Haskell programming language and now I found out that it's possible to call Haskell functions from C programs. During my Haskell studies, I created a word frequency counter with Haskell and I would like to try to call that function from a C program, but I don't know how to do it. I found these two websites on haskell.org:
Foreign C types (Haskell module)
Despite that, I'm a bit lost which types to use. My haskell programs is a pipeline of following functions:
putStr . unlines . map testF . sortedTree
where my own functions
- testF is type of testF :: Show a => ([Char],a) -> [Char]
- sortedTree is type of sortedTree :: (Num a, Ord a) => [Char] -> [([Char],a)]
I'm quite sure that I need to convert the types of each function to C types, instead of converting just the function that calls the pipeline. The type of the "main" function is
fileFreq :: [Char] -> IO ()
Besides all this, I'm using a Haskell binary tree, that isn't prelude type.
Here is the whole Haskell code:
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 }
Can anyone guide me a bit with this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您需要做的是为需要暴露给 C 的函数创建包装函数,并完成从 C 类型转换为 haskell 类型的工作。
您还需要启用ForeignFunctionInterface扩展,并且haskell代码中可能发生的任何异常都需要在包装函数中处理。
例如,如果您只需要向 C 公开顶级函数 fileFreq,您可以添加如下函数:
创建一个将 C 字符串编组为 haskell 字符串的函数(使用foreign.c.string 中的函数),调用fileFreq 函数并将异常转换为 C 错误代码(如果发生异常则为 -1,否则为 0)。
然后您需要使用导出它
,当然您需要
在模块顶部添加:。
然后,您可以按照您提供的链接中的说明将其编译为 C 存根和头文件,并创建一个可以使用 ghc 编译的 C 文件。
当然可以包装您拥有的任何函数,您只需要确保处理可能的异常并在 C 类型和 haskell 类型之间进行编组。
我修改后的完整代码是:
What you will need to do is to create wrapper functions for the functions you need exposed to C and there do the work of converting from C-types to haskell types.
You will also need to enable the ForeignFunctionInterface extension, also any exceptions that may occur in the haskell code need to be handled in the wrapper functions.
For example, if you only need to expose your top-level function fileFreq to C you could add a function like:
to create a function that marshals a C-string into a haskell string (using functions from Foreign.C.String), calls your fileFreq function and translates exceptions to C error codes (-1 if exception happened, 0 otherwise).
Then you need to export it using
and of course you need to add:
at the top of your module.
Then you can follow the instructions in the links you provided to compile this to a C-stub and header file and create a C-file that you can compile with ghc.
It is of course possible to wrap any function you have, you just need to make sure to handle possible exceptions and to marshal between C-types and haskell types.
The complete code with my modifications is: