I want to open a file in Haskell, but I want the top level function to be called from C (I want to pass the filepath from C).
I'm having trouble getting the filepath
CString
into a type that I can use readFile
on.
Here's my first attempt, adapting the example from the docs:
{-# LANGUAGE ForeignFunctionInterface #-}
import Foreign.C.Types
import Foreign.C (CString, peekCString)
openFileDoStuff :: String -> IO Bool
openFileDoStuff filename = do
lines <- (fmap lines . readFile) filename
print lines
-- do stuff with lines
return True
openFilepathHs :: CString -> IO Bool
openFilepathHs cstr = openFileDoStuff (peekCString cstr)
foreign export ccall openFilepathHs :: CString -> IO Bool
I get a compiler error passing (peekCString cstr)
to openFileDoStuff
:
• Couldn't match type: IO String
with: [Char]
If I change the signature of my function to openFileDoStuff :: IO String -> IO Bool
, I then can't use the filename
parameter in the readFile
call:
• Couldn't match type: IO String
with: [Char]
If it's not abundantly clear, I am a newbie in Haskell. I know there's no way to convert IO String -> String
, but there must be a way to actually use the CString
type.
CodePudding user response:
I needed to run the IO String
and bind it to a variable:
{-# LANGUAGE ForeignFunctionInterface #-}
import Foreign.C.Types
import Foreign.C (CString, peekCString)
openFileDoStuff :: IO String -> IO Bool
openFileDoStuff filename = do
filenameString <- filename
lines <- (fmap lines . readFile) filenameString
print lines
-- do stuff with lines
return True
openFilepathHs :: CString -> IO Bool
openFilepathHs cstr = openFileDoStuff (peekCString cstr)
foreign export ccall openFilepathHs :: CString -> IO Bool
CodePudding user response:
Use >>=
to combine IO actions.
openFilepathHs cstr = peekCString cstr >>= openFileDoStuff
Actually, this pattern of passing a piece of data through successive IO transformations is so common it has a standard combinator for abbreviation.
openFilepathHs = peekCString >=> openFileDoStuff
You can also use do
syntax to hide calls to >>=
, but as a beginner I personally found do
syntax very difficult to understand before I understood how to make calls to >>=
myself.
openFilepathHs cstr = do
cstrContents <- peekCString cstr
openFileDoStuff cstrContents