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
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型?