Haskell: использовать список, созданный в функции ввода-вывода в другой, не входящей в функцию - PullRequest
0 голосов
/ 18 марта 2020

Я использую функцию String -> IO [x] для чтения содержимого файла в список, где каждый элемент в списке является словом из файла.

Однако я хотел бы использовать список [x] в качестве входа для другой функции. Моя проблема в том, что я не понимаю, как получить доступ к списку basi c [x], а не к списку IO [x], созданному в моей первоначальной функции. Я пытался обойти это для тестирования, используя GHCI и

k <- listRead "file.txt"

, а затем используя этот k в качестве ввода в моей следующей функции, которая принимает только список [x] в качестве ввода.

Как я могу использовать "внутренний" список [x] вместо возвращенного IO [x], который возвращает моя первоначальная функция?

Ответы [ 2 ]

4 голосов
/ 18 марта 2020

Это то, для чего предназначен класс Monad.

foo :: String -> IO [SomeType]
bar :: [SomeType] -> IO SomeOtherType

затем

baz :: String -> IO SomeOtherType
baz name = foo name >>= bar

(или после импорта Control.Monad, baz = foo >=> bar).

Если все, что у вас есть, это какая-то функция bar' :: [SomeType] -> SomeOtherType, то вы можете определить

bar :: [SomeType] -> IO SomeOtherType
bar = return . bar'

Обратите внимание, что вы никогда не сможете "получить" значение типа [SomeType]; Вы можете создавать новые действия ввода-вывода, которые используют значение только после выполнения действия ввода-вывода.

0 голосов
/ 18 марта 2020

Просто поместите эту строку, которую вы использовали в GHCi, в блок do:

do
    k <- listRead "file.txt"    
    let r = yourPureFunction k
    return r

В do запись , для строки x <- mx, всякий раз, когда mx :: M <b>a</b> для некоторой монады M, у нас есть x :: <b>a</b>.

Таким образом yourPureFunction :: <b>a</b> -> <b>b</b> применяется к аргументу a внутри из M, и объединенное значение monadi c, представленное блоком do, имеет тип M <b>b</b>, поскольку return имеет тип return :: <b>b</b> -> M <b>b</b>, а общий тип do block - это тип его последнего выражения.

Приведенный выше код действительно является синтаксическим представлением более высокого уровня / encodable как / (return . yourPureFunction) =<< listRead "file.txt", что также совпадает с yourPureFunction <$> listRead "file.txt"(<$>) = fmap), но это не главное.

...