Интуиция для MaybeT

Я пытаюсь понять MaybeT запустив несколько примеров в ghci:

λ: import Control.Monad.Trans.Maybe
λ: let x = return $ 42 :: MaybeT (Either String) Int
λ: :t x
x :: MaybeT (Either String) Int

Затем я запустил его:

λ: runMaybeT x
Right (Just 42)

Пожалуйста, оцените меня, yтакой, что

runMaybeT y === Left (Just "...")
runMaybeT y === Left Nothing
runMaybeT y === Right Nothing

2 ответа

Вы никогда не получите Left Nothing или же Left (Just ..)Монада здесь Either String …, так что слева у вас всегда будет String,

Вот что вы можете получить:

> let y = fail "Failed" :: MaybeT (Either String) Int
> runMaybeT y
Right Nothing
> let y = lift (Left "Failed") :: MaybeT (Either String) Int
> runMaybeT y
Left "Failed"

Это может помочь понять, что происходит под капотом с MaybeT...

В монаде IO есть вычисления, например

putStrLn "Hello, world!" :: IO ()
getContents :: IO String

и т.д. Все эти вычисления имеют тип IO a и на самом деле переменная типа a неограниченно - это может быть любой тип. С помощью return мы можем создать вычисление IO IO a для любого типа a,

Вы можете думать о MaybeT IO как те вычисления IO, которые возвращают значение Maybe.

Например, getContents является IO расчет, но не MaybeT IO вычисление. Тем не менее, есть своего рода очевидный способ конвертировать getContents в MaybeT IO вычисление - просто оберните его вывод в Just конструктор:

lift getContents   ===   fmap Just getContents

lift это способ продвижения IO вычисление в MaybeT IO вычисление. Применяя это к return_IO (return функция для IO монада) имеем:

return_(MaybeT IO) === lift return_IO === fmap Just return_IO

То есть, return 3MaybeT IO монада) такая же как return (Just 3) в IO монада.

runMaybeT и MaybeT являются противоположностями друг друга

Теперь посмотрим на определение MaybeT

newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }

Это также описывает идею о том, что вычисления в MaybeT m такие же, как вычисления в m которые возвращают значение Maybe. Функции:

MaybeT    :: m (Maybe a) -> MaybeT m a
runMaybeT :: MaybeT m a  -> m (Maybe a)

являются противоположностями друг друга и на самом деле ничего не делают, кроме добавления или удаления оболочки нового типа. В случае с IO монада:

MaybeT    :: IO (Maybe a) -> MaybeT IO a
runMaybeT :: MaybeT IO a  -> IO (Maybe a)

Рассматривая пример в вашем вопросе, мы видим, что вычисления в MaybeT (Either String) по существу такие же, как значения типа Either String (Maybe a) для любого типа a, Это приводит к следующим возможностям:

  • Left какой-то строки
  • Right (Just ...)
  • Right Nothing

Все это существует в Either String (Maybe a) и если мы применим конструктор MaybeT для каждого из них мы получаем соответствующие значения в MaybeT (Either String) a,

В частности, чтобы найти y улица

runMaybeT y == Right Nothing

просто используйте:

          y = MaybeT (Right Nothing)

Снова, runMaybeT а также MaybeT являются противоположностями друг друга, поэтому вы можете получить тот же результат, применяя MaybeT в обе стороны.

Другие вопросы по тегам