Haskell: вставка каждой строки из файла в список
в настоящее время я работаю над проектом с Haskell, и нашли себе неприятности. Я должен читать и вставлять в список каждую строку в "словаре".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
предполагается получить каждую строку (я знаю, что она получает каждую строку, так как замена "inpStr:list" на "putStrLn inpStr" работает правильно, отображая все строки) и вставить его в список, но я получаю следующее ошибка:
Couldn't match expected type `IO' against inferred type `[]'
вероятно, потому что hGetLine-это не строка, а строка ввода-вывода, которую я понятия не имею, как обрабатывать, чтобы получить правильную строку, которую я могу вставить в свой список. Я понятия не имею, как это можно решить, или в чем проблема, но если кто-то имеет представление о том, как правильно получить каждую строку в файле в список, я был бы признателен.
спасибо заранее!
2 ответов
в строке, где происходит ошибка, Haskell ожидает "IO a", но вы даете ему []. Упрощая вещи много, на блоке do на монаде IO каждая строка либо:
- что-то, что возвращает значение типа "IO a"; значение типа "a" внутри него отбрасывается (поэтому "a" часто является "()")
- a
- a let, который ничего не делает, кроме как дать имя значению
в этом блоке do "hgetline inh" возвращает "строку ввода-вывода", а строка внутри нее извлекается и получает имя inpStr. Следующая строка, поскольку она не является ни let, ни
let list' = inpStr:list
это создает новый список, состоящий из Строка, за которой следует исходный список, и дает ему имя "список".
измените следующую строку, чтобы использовать "list" вместо "list" (таким образом, передав ей новый список). Эта строка вызывает (рекурсивно) mainloop, который прочитает еще одну строку, вызовет себя и так далее. После прочтения всего файла он вернет что-то с типом" IO ()". Этот "IO ()" будет возвращен в блок do в loadNums. Поздравляю, вы только что создали список со строками, прочитанными из файла, в обратный порядок (так как вы добавляли в начало списка), а затем ничего не сделали.
Если вы хотите что - то сделать с ним, измените "return ()" на "return list"; return будет генерировать значение типа "IO [String]" со списком внутри него (return не делает ничего, кроме инкапсуляции значения), которое вы можете извлечь в loadNums с
остальное остается в качестве упражнения для читателя.
Если это не для домашней работы или чего-то еще, нет причин использовать так много усилий. Повторное использование лениво!
getLines = liftM lines . readFile
main = do
list <- getLines "dictionary.txt"
mapM_ putStrLn list