Ответ 1
Что вам нужно будет сделать, так это создать функции-обертки для функций, которые вам нужно подвергать C, и выполнять работу по преобразованию из типов C в типы haskell.
Вам также необходимо включить расширение ForeignFunctionInterface, а также любые исключения, которые могут возникнуть в коде haskell, должны обрабатываться в функциях обертки.
Например, если вам нужно только выставить функцию верхнего уровня на FF, чтобы добавить 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-stub и заголовка и создать C файл, который вы можете скомпилировать с помощью ghc.
Конечно, можно обернуть любую имеющуюся у вас функцию, вам просто нужно будет обработать возможные исключения и маршалировать между типами 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