How to choose right Haskell C type?

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:

Calling Haskell from C

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 : ":" : " ttt " : show n : [])
    
    concord = putStr . unlines . map testF . sortedTree
    
    fileFreq filename = do { text <- readFile filename; concord text }
    

    Can anyone guide me a bit with this?


    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:

    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
    

    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

    foreign export ccall fileFreq_hs :: CString -> IO CInt
    

    and of course you need to add:

    {-# LANGUAGE ForeignFunctionInterface #-}
    

    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:

    {-# 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/33150.html

    上一篇: 循环类型同义词声明

    下一篇: 如何选择正确的Haskell C型?