如何选择正确的Haskell C型?

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

从C调用Haskell

外部C类型(Haskell模块)

尽管如此,我有点丢失了哪些类型的使用。 我的haskell程序是一系列以下功能:

putStr。 不合格。 映射testF。 sortedTree

我自己的职责在哪里

  • testFtestF的类型::显示a =>([Char],a) - > [Char]
  • sortedTreesortedTree的类型::(数字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 : ":" : " ttt " : 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存根和头文件,并创建一个可以用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 : ":" : " ttt " : 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
    
    链接地址: http://www.djcxy.com/p/33149.html

    上一篇: How to choose right Haskell C type?

    下一篇: Why does GHC infer type of `IO b` for an application of `hSetBuffering`?