我目前正在与Haskell合作,并发现自己遇到了一些麻烦.我应该在"dictionary.txt"文件中读取并插入列表中的每一行,但我似乎无法这样做.我有这个代码:
main = do let list = [] loadNums "dictionary.txt" list loadNums location list = do inh <- openFile location ReadMode mainloop inh list hClose inh mainloop inh list = do ineof <- hIsEOF inh if ineof then return () else do inpStr <- hGetLine inh inpStr:list mainloop inh list
它应该得到每一行(我知道它确实得到每一行,因为用"putStrLn inpStr"替换"inpStr:list"正常工作,显示所有行),并将其插入列表但我得到以下错误:
Couldn't match expected type `IO' against inferred type `[]'
可能是因为hGetLine不是一个字符串,而是一个IO字符串,我不知道如何处理以获得一个正确的字符串,我可以在我的列表中插入.我不知道如何解决这个问题,或者问题究竟是什么,但如果有人知道如何正确地将文件中的每一行都放入列表中,我会很感激.
提前致谢!
除非这是作业或其他东西,否则没有理由使用这么多的努力.重用是懒惰的!
getLines = liftM lines . readFile main = do list <- getLines "dictionary.txt" mapM_ putStrLn list
但是,由于您似乎仍在学习Haskell,因此了解CesarB编写的内容非常重要.
在发生错误的行中,Haskell期望"IO a",但是你给它一个[].在IO monad的do块上简化了很多事情,每一行都是:
返回"IO a"类型值的东西; 其中"a"类型的值被丢弃(因此"a"通常是"()")
一个< - 表达式,它执行相同的操作,但不是丢弃"a"类型的值,而是给出了< - 左侧的名称 -
一个let,它只是给一个值赋一个名字
在那个do块中,"hGetLine inh"返回一个"IO String",并且提取其中的String并给出名称inpStr.下一行,因为它既不是let也不是< - ,应该有一个类型"IO a",它不会(因此导致编译器错误).你可以做什么,因为你已经有了String,是一个let:
let list' = inpStr:list
这将创建一个新的列表,其中包含String后跟原始列表,并为其命名为"list".
更改以下行以使用"list"而不是"list"(从而将新列表传递给它).该行调用(递归)mainloop,它将读取另一行,调用自身,依此类推.读完整个文件后,它将返回"IO()"类型的内容.这个"IO()"将返回到loadNums的do块.恭喜你,你刚刚创建了一个列表,其中包含从文件中读取的行,顺序相反(因为你要附加到列表的头部),然后对它没有任何作用.
如果你想对它做点什么,把"return()"改为"return list"; return将生成一个类型为"IO [String]"的值,其中包含列表(return只会封装该值),您可以使用< - syntax在loadNums中提取该值.
其余部分留给读者练习.