我对Haskell很新,我试图简单地将文件读入字符串列表。我想要列表中每个元素的一行文件。但我遇到了一个我不明白的类型问题。这是我为我的功能写的:
readAllTheLines hdl = (hGetLine hdl):(readAllTheLines hdl)
编译好。我原以为文件句柄需要与openFile
返回的文件句柄相同。我试图通过执行以下操作简单地显示上述函数中的列表:
displayFile path = show (readAllTheLines (openFile path ReadMode))
但是当我尝试编译它时,我收到以下错误:
filefun.hs:5:43: 无法将预期类型'Handle'与实际类型'IO Handle'匹配 在'openFile'调用的返回类型中 在'readAllTheLines'的第一个参数中,即 '(openFile path ReadMode)' 在'show'的第一个参数中,即 '(readAllTheLines(openFile path ReadMode))'
所以看起来openFile返回IO Handle
,但hGetLine
需要一个普通的Handle
。我误解了这两个功能的用途吗?它们不打算一起使用吗?或者只是我缺少一件作品?
答案 0 :(得分:6)
使用readFile
和lines
作为更好的选择。
readLines :: FilePath -> IO [String]
readLines = fmap lines . readFile
回到您的解决方案openFile
会返回IO Handle
,因此您必须执行操作才能获得Handle
。在阅读之前,您还必须检查Handle
是否处于eof状态。使用上述解决方案要简单得多。
import System.IO
readAllTheLines :: Handle -> IO [String]
readAllTheLines hndl = do
eof <- hIsEOF hndl
notEnded eof
where notEnded False = do
line <- hGetLine hndl
rest <- readAllTheLines hndl
return (line:rest)
notEnded True = return []
displayFile :: FilePath -> IO [String]
displayFile path = do
hndl <- openFile path ReadMode
readAllTheLines hndl