Не удалось сопоставить тип «IO String» с «[Char]» - PullRequest
0 голосов
/ 09 апреля 2019

У меня есть проект для школы, в котором я должен читать из файла, поскольку мне дано указание на функцию, которую я должен реализовать.

У меня уже есть следующая функция, которую я предполагаюон читает файл с именем "имя_файла":

getInputTest file_name = do  
    x <- readFile file_name
    return x

Далее, мне нужно проанализировать каждую строку текста, чтобы получить вектор строк, каждый элемент вектора представляет собой одну строкуфайла.Вот где я получаю заголовок функции, которую я должен реализовать:

parse :: String -> [Instr]

Первый аргумент этой функции должен быть всем, что читается из файла (все строки), и [Instr] долженбыть сформирован из всех строк из файла, каждый элемент вектора является одной строкой (я должен был выбрать «Instr», и я попытался выбрать его «String», но он не работает)

Я уже пробовал это:

parse file_name = lines (getInputTest file_name)

Но я продолжаю получать ошибки, такие как: "Не удалось сопоставить тип 'IO String' с '[Char]'".

Что я делаюнеправильно и как я могу это исправить?Учитывая, что заголовок функции "parse" не должен изменяться.

Ответы [ 2 ]

1 голос
/ 09 апреля 2019

String равно [Char], поэтому компилятор жалуется, что он заключен в IO. Прочитайте, например. https://wiki.haskell.org/Introduction_to_IO для объяснения.

Чтобы исправить это, вам нужно «поднять» вашу функцию синтаксического анализа в точке вызова, чтобы вместо нее работать на IO String. Это обычно требует, например. fmap / <$>, но работая в нотации do, ее можно добавить, например, написав. return $ parse x.

0 голосов
/ 09 апреля 2019
getInputTest file_name = do  
    x <- readFile file_name
    return x

Это эквивалентно любому из следующего:

getInputTest :: FilePath -> IO String
getInputTest fileName = readFile fileName >>= \x -> return x
getInputTest fileName = readFile fileName >>= return
getInputTest fileName = readFile fileName
getInputTest = readFile
parse :: String -> [Instr]
parse file_name = lines (getInputTest file_name)

Поскольку getInputTest :: FilePath -> IO String и lines :: String -> [String], вы должны, как говорит А. Тайлер, поднимать lines так, чтобы это работало в контексте IO.

Делая fmap lines, вы получаете тип Functor f => f String -> f [String], который при специализации от f до IO становится IO String -> IO [String]. Это соответствует типу вывода readFile, поэтому функции могут составлять:

parse :: FilePath -> IO [String]
parse fileName = fmap lines (getInputTest fileName)

Я не уверен, что это за тип Instr, и если есть дальнейший разбор, чем то, что lines делает, чтобы превратить String строку в Instr; если нет, возможно, вы могли бы объединить две функции в одну:

type Instr = String

fromFile :: FilePath -> IO [Instr]
fromFile = fmap lines . readFile
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...