Ответ 1
В строке, где происходит ошибка, Haskell ожидает "IO a" , но вы даете ему []. Упрощая многое, на блоке do на монаде IO, каждая строка либо:
- Что-то, возвращающее значение типа "IO a" ; значение типа "a" в нем отбрасывается (поэтому "a" часто "()" )
- A < - выражение, которое делает то же самое, но вместо того, чтобы отбрасывать значение типа "a" , дает ему имя слева от < -
- Позволяет, что не более чем дает имя значению
В этом блоке "hGetLine inh" возвращает строку "IO String", а String внутри нее извлекается и получает имя inpStr. Следующая строка, так как у нее ни let, ни a < - не должно быть типа "IO a" , чего нет (что вызывает ошибку компилятора). Что вы можете сделать вместо этого, поскольку у вас уже есть String, есть let:
let list' = inpStr:list
Создает новый список, состоящий из строки, за которой следует исходный список, и дает ему имя "list" .
Измените следующую строку, чтобы использовать "list" вместо "list" (таким образом, передавая ему новый список). Эта строка вызывает (рекурсивно) mainloop, который будет читать еще одну строку, называть себя и т.д. После прочтения всего файла он вернет что-то с типом "IO()". Этот "IO()" будет возвращен блоку do в loadNums. Поздравляем, вы только что создали список с строками, считанными из файла, в обратном порядке (с тех пор, как вы добавили в начало списка), а затем ничего не сделали для него.
Если вы хотите что-то сделать, измените "return()" на "return list"; return будет генерировать значение типа "IO [String]", со списком внутри него (return делает не что иное, как инкапсуляцию значения), которое вы можете извлечь при загрузкеNums с помощью < - синтаксиса.
Остальное остается в качестве упражнения для читателя.