Библиотека исключений Edward Kmett не предоставляет MonadMask экземпляр для ExceptT.
Бен Гамари однажды спросил об этом, а затем пришел к выводу, что это объясняется документацией. Это самый близкий вид, который я могу найти:
Обратите внимание, что этот пакет предоставляет экземпляр
MonadMask
дляCatchT
. Этот экземпляр действителен только в том случае, если базовая монада не обеспечивает возможность множественного выхода. Например,IO
илиEither
будут недопустимыми базовыми монадами, но допустимыReader
илиState
.
Но его значение для меня не самоочевидно. Что означает "множественный выход" и почему он запрещает экземпляр MonadMask
?
[...] "MonadMask", который позволяет гарантировать выполнение определенных действий даже при наличии исключений (как синхронных, так и асинхронных). Чтобы обеспечить эту гарантию, стек монады должен иметь возможность контролировать ход выполнения. В частности, это исключает экземпляры для [...] Monads с несколькими точками выхода, например
ErrorT
надIO
.
Возможно, было бы более понятно задать этот альтернативный вопрос: если мы отложим трансформаторы и рассмотрим несколько более простой тип:
data IOEither a = IOEither { unIOEither :: IO (Either String a) }
deriving Functor
Кажется, что мы действительно можем написать экземпляр MonadMask
:
instance Applicative IOEither where
pure = IOEither . return . Right
IOEither fIO <*> IOEither xIO = IOEither $
fIO >>= either (return . Left) (\f -> (fmap . fmap) f xIO)
instance Monad IOEither where
IOEither xIO >>= f = IOEither $
xIO >>= either (return . Left) (\x -> unIOEither (f x))
instance MonadThrow IOEither where
throwM e = IOEither (throwM @IO e)
instance MonadCatch IOEither where
catch (IOEither aIO) f = IOEither $ catch @IO aIO (unIOEither . f)
instance MonadMask IOEither where
mask f = IOEither $ mask @IO $ \restore ->
unIOEither $ f (IOEither . restore . unIOEither)
uninterruptibleMask f = IOEither $ uninterruptibleMask @IO $ \restore ->
unIOEither $ f (IOEither . restore . unIOEither)
Является ли этот экземпляр, который я написал, не работает должным образом?