Haskell:将文件中的每一行插入到列表中 [英] Haskell: Inserting every line from a file into a list

查看:105
本文介绍了Haskell:将文件中的每一行插入到列表中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在与Haskell合作项目,并且发现自己有些麻烦。我应该阅读并在dictionary.txt文件中的每一行插入一个列表,但我似乎无法这样做。我有这样的代码:

  main = do 
let list = []
loadNumsdictionary .txtlist

loadNums location list = do
inh< - openFile位置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工作正常,显示所有行),并将其插入列表中,但出现以下错误:

 无法匹配预期的类型`IO'与推断的类型`[]'

可能是因为hGetLine不是一个字符串,而是一个IO字符串,我不知道如何处理以获得一个我可以在我的列表中插入适当的字符串。我不知道如何解决这个问题,或者问题是什么,但是如果任何人有任何想法如何正确地将文件中的每一行都列入列表,我会很感激。



在此先感谢!

解决方案

在发生错误的行中,Haskell期待IO一个,但你给它一个[]。简化事情很多,在IO monad上的do块上,每一行都是:


  • 返回IO一种;其中的a类型的值被丢弃(所以a通常是())

  • 一个< - 表达式,它做同样的事情,丢弃a类型的值将给它赋予< -

  • 左侧的名称let,除了给一个值赋一个名字外



  • 在那个块中,hGetLine inh返回一个IO String,并且其中的String被提取并且给出名字inpStr。下一行,因为它既不是let也不是< - ,应该有一个类型IO a,它不会(因此导致编译器错误)。你可以做的,因为你已经有了字符串,是一个让:

      let list'= inpStr:list 

    这将创建一个新的列表,其中包含String,后跟原始列表,并为其指定名称list '。



    更改下列行以使用list而不是list(从而将新列表传递给它)。该行调用(递归)mainloop,它将读取更多行,调用自身,等等。读完整个文件后,它将返回一些带有IO()类型的内容。这个IO()将返回到loadNums处的do块。恭喜,您刚刚创建了一个列表,其中包含从文件中读取的行,顺序相反(因为您添加到列表的头部),然后什么也没做。



    如果你想对它做些什么,把return()改为return list;返回值将生成一个类型为IO [String]的值,其中的列表(返回只是封装值),您可以使用< - 语法在loadNums中提取该值。



    其余部分留给读者练习。


    I'm currently working on project with Haskell, and have found myself some trouble. I'm supposed to read and insert into a list each line in a "dictionary.txt" file, but I can't seem to do so. I've got this code:

    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
    

    It is supposed to get every line (I know it does get every line, since replacing the "inpStr:list" with a "putStrLn inpStr" works correctly, displaying all lines), and insert it into a list but I get the following error:

    Couldn't match expected type `IO' against inferred type `[]'
    

    Probably because the hGetLine isn't a String, but a IO String, which I have no idea how to handle in order to obtain a proper string I can insert in my list. I have no idea how this could be solved, or what the problem is exactly, but if anyone has any idea of how to properly get every line in a file into a list, I'd appreciate it.

    Thanks in advance!

    解决方案

    In the line where the error happens, Haskell is expecting "IO a", but you are giving it a []. Simplifying things a lot, on a do block on the IO monad, every line is either:

    • Something which returns a value of the "IO a" type; the value of the "a" type within it is discarded (so the "a" is often "()")
    • A <- expression, which does the same thing but instead of discarding the value of the "a" type gives it the name to the left of the <-
    • A let, which does nothing more than give a name to a value

    In that do block, the "hGetLine inh" returns an "IO String", and the String within it is extracted and given the name inpStr. The next line, since it's neither a let or a <-, should have a type "IO a", which it doesn't (thus causing the compiler error). What you can do instead, since you already have the String, is a let:

    let list' = inpStr:list
    

    This creates a new list consisting of the String followed by the original list, and gives it the name of "list' ".

    Change the following line to use "list' " instead of "list" (thus passing it the new list). That line calls (recursively) mainloop, which will read one more line, call itself, and so on. After reading the whole file, it will return something with the "IO ()" type. This "IO ()" will be returned to the do block at loadNums. Congratulations, you just created a list with the lines read from the file, in reverse order (since you were appending to the head of the list), and then did nothing to it.

    If you want to do something to it, change the "return ()" to "return list"; the return will generate a value of type "IO [String]", with the list within it (return does nothing more than encapsulating the value), which you can extract at loadNums with the <- syntax.

    The rest is left as an exercise to the reader.

    这篇关于Haskell:将文件中的每一行插入到列表中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆