Монадные трансформаторы с IO и Maybe - PullRequest
0 голосов
/ 27 апреля 2019

Я пытаюсь сложить моно и ввод-вывод, но либо недостаточно хорошо понимаю монадные трансформаторы, либо это невозможно с помощью трансформаторов.Может ли кто-нибудь помочь мне понять это?

f :: String -> Maybe String

main :: IO ()
main = do
  input <- getLine            -- IO String
  output <- f input           -- Maybe String (Can't extract because it is IO do block)
  writeFile "out.txt" output  -- gives error because writeFile expects output :: String

В приведенном выше упрощенном примере у меня есть функция f, которая возвращает Maybe String, и я хотел бы иметь аккуратный способ извлечь это вIO сделать блок.Я попытался

f :: String -> MaybeT IO String

main :: IO ()
main = do
  input <- getLine              -- IO String
  output <- runMaybeT (f input) -- Extracts output :: Maybe String instead of String
  writeFile "out.txt" output    -- gives error because writeFile expects output :: String

, который позволяет мне извлечь Maybe String во второй строке блока do, но мне нужно извлечь строку из этого.Есть ли способ сделать это без использования case?

1 Ответ

4 голосов
/ 27 апреля 2019

Давайте на минутку остановимся на вашем первом фрагменте. Если f input является Maybe String, и вы хотите передать его результат в writeFile "out.txt", что занимает String, вам нужно иметь дело с возможностью f input быть Nothing. Вам не нужно буквально использовать регистр. Например:

  • maybe из Prelude - анализ случая, упакованный как функция;

  • fromMaybe из Data.Maybe позволяет легко указать значение по умолчанию, если это имеет смысл для вашего варианта использования;

  • traverse_ и for_ с Data.Foldable могут использоваться для беззвучного игнорирования Nothing -ness:

    for_ (f input) (writeFile "out.txt") -- Does nothing if `f input` is `Nothing`.
    

Тем не менее, независимо от того, что вы решите делать, это будет как-то обрабатывать Nothing.

Что касается MaybeT, вам не нужны монадные трансформаторы здесь. MaybeT IO предназначен для случаев, когда требуется что-то вроде Maybe вычислений, но в который вы также можете включить IO вычислений. Если f :: String -> Maybe String уже делает то, что вы хотите, вам не нужно добавлять базовый слой IO к нему.

...