Борьба с IO при чтении файла конфигурации в Haskell - PullRequest
0 голосов
/ 02 февраля 2020

У меня есть входные данные, предназначенные для моих еще не написанных приложений Haskell, которые находятся в файле. Я не обновляю файл. Мне просто нужно прочитать файл и передать его в мою функцию Haskell, которая ожидает список строк. Но чтение файла, конечно, дает IO объекты данных. Я узнал, что с помощью операции <- можно каким-то образом «извлечь» строки, упакованные в структуру IO, поэтому я попробовал эту попытку:

run :: [String]
run = do
  datadef_content <- readFile "play.txt" -- yields a String
  let datadef = lines datadef_content -- should be a [String]
  return datadef

Я поместил это в файл play.hs и загрузил его из ghci по

:l play

К моему удивлению, я получил сообщение об ошибке для readFile строки

 Couldn't match type ‘IO’ with ‘[]’
 Expected type: [String]
   Actual type: IO String

и для return сообщение об ошибке

 Couldn't match type ‘[Char]’ with ‘Char’
 Expected type: [String]
   Actual type: [[String]]

Первое, кажется, указывает на то, что я не смог избавиться от IO, а последнее сообщение, кажется, предполагает, что lines будет вернуть список списка строк, что также не имеет смысла для меня.

Как я могу сделать это правильно?

1 Ответ

5 голосов
/ 02 февраля 2020

Вы объявляете run значением [String]. Но return не является ключевым словом, которое предоставляет возвращаемое значение функции; - это функция с типом Monad m => a -> m a. return datadef создает значение типа IO [String], которое становится возвращаемым значением функции.

Решение состоит в том, чтобы предоставить правильный тип возврата для run:

run :: IO [String]
run = do
    ...

run также можно определить более кратко как

run = fmap lines (readFile "play.txt")

Хотя синтаксис do предполагает, что нет способа извлечь значение из действия IO; все, что вы можете сделать, это «pu sh» вызов lines в действие.

...