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!
Unless this is for homework or something, there's no reason to use so much effort. Reuse is lazy!
But as you seem to still be learning Haskell, it is important for you to understand what CesarB has written.
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:
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:
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.