如何选择合适的Haskell C型?

zap*_*lec 10 c haskell types ffi

我研究了一些Haskell编程语言,现在我发现可以从C程序中调用Haskell函数.在我的Haskell研究期间,我用Haskell创建了一个单词频率计数器,我想尝试从C程序调用该函数,但我不知道该怎么做.我在haskell.org上找到了这两个网站:

从C调用Haskell

外国C类型(Haskell模块)

尽管如此,我还是有点迷失哪种类型.我的haskell程序是以下功能的管道:

putStr.unlines.map testF.sortedTree

我自己的功能

  • testFtestF的类型:: Show a =>([Char],a) - > [Char]
  • sortedTreesortedTree的类型::(Num a,Ord a)=> [Char] - > [([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 }
Run Code Online (Sandbox Code Playgroud)

任何人都可以指导我一点吗?

dna*_*naq 7

您需要做的是为您需要向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
Run Code Online (Sandbox Code Playgroud)

创建一个将C字符串封送到haskell字符串中的函数(使用Foreign.C.String中的函数),调用fileFreq函数并将异常转换为C错误代码(如果发生异常,则为-1,否则为0).

然后你需要使用它导出它

foreign export ccall fileFreq_hs :: CString -> IO CInt
Run Code Online (Sandbox Code Playgroud)

当然你需要添加:

{-# LANGUAGE ForeignFunctionInterface #-}
Run Code Online (Sandbox Code Playgroud)

在您的模块的顶部.

然后,您可以按照您提供的链接中的说明将其编译为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,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 :: (Ord t, Num t) => String -> [([Char], t)]
sortedTree x = sortBy (\(x,y) (p,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
Run Code Online (Sandbox Code Playgroud)