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