为什么Haskell代码会出现parse error on input ‘isFileEnd’错误
问题排查与解决
1 解析错误的直接原因
你遇到的parse error on input ‘isFileEnd’是Haskell缩进规则不满足导致的:where关键字后的绑定函数readDataFrom的do块内的代码,缩进必须比readDataFrom的起始位置更靠右,你原代码里isFileEnd所在行的缩进级别低于readDataFrom的起始位置,编译器无法识别这是readDataFrom内部的代码,直接抛出解析错误。
2 其他隐藏的类型/逻辑错误
除了缩进外,你的代码还有多处不匹配的问题:
- 签名中
func的类型是Handle -> IO a,但你调用时传入的是hGetLine返回的String类型的info,类型不匹配 readTableFile签名声明返回IO [a],但你当前实现没有收集func的执行结果,反而返回的是IO ()withFile会在传入的lambda执行完成后自动关闭文件句柄,你尝试把withFile的返回值绑定到fileHandle没有任何意义,lambda执行完成后句柄已经失效readDataFrom当前返回的是IO String,和你需要的返回列表的逻辑不符
3 修正后的完整代码
import System.IO (Handle, withFile, ReadMode, hIsEOF, hGetLine) -- 调整func的类型为String -> IO a,匹配你传入每行字符串调用的逻辑 readTableFile :: String -> (String -> IO a) -> IO [a] readTableFile file func = withFile file ReadMode readDataFrom where -- readDataFrom缩进级别高于where关键字 readDataFrom :: Handle -> IO [a] readDataFrom fileHandle = do -- do块内代码缩进高于readDataFrom的起始位置 isFileEnd <- hIsEOF fileHandle if isFileEnd then return [] else do info <- hGetLine fileHandle res <- func info rest <- readDataFrom fileHandle return (res : rest)
4 使用示例
如果你需要打印每行内容的同时收集长度,可以这么调用:
main :: IO () main = do lineLengths <- readTableFile "test.txt" (\line -> do putStrLn line return $ length line ) print lineLengths
内容的提问来源于stack exchange,提问作者Vic
相关产品推荐
相关产品推荐

