- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
Edward Kmett 的异常库不提供MonadMask ExceptT 的实例.
Ben Gamari once asked about this然后得出结论,文档对此进行了解释。这是我能找到的最接近相关的段落:
Note that this package does provide a
MonadMask
instance forCatchT
. This instance is only valid if the base monad provides no ability to provide multiple exit. For example,IO
orEither
would be invalid base monads, butReader
orState
would be acceptable.
但它的意义对我来说并不是不言而喻的。 “多次退出”是什么意思以及为什么它禁止 MonadMask
实例?
[...] 'MonadMask', which allows you to guarantee that certain actions are run, even in the presence of exceptions (both synchronous and asynchronous). In order to provide that guarantee, the monad stack must be able to control its flow of execution. In particular, this excludes instances for [...] Monads with multiple exit points, such as
ErrorT
overIO
.
也许问这个替代问题会更清楚:如果我们搁置变压器并考虑稍微简单的类型:
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)
我写的这个实例不能正常工作吗?
最佳答案
下面的程序演示了您的实例的问题:您可以使用 Left
提前退出,从而导致终结器永远不会运行。这与 MonadMask
文档中规定的法律相反,该法律要求无论发生什么情况,都执行 f `finally` g
g
在f
中。终结器永远不会运行的原因非常简单:如果没有抛出异常 finally
(或 bracket
这是 finally
的实现方式)之后使用 >>=
运行终结器,但如果左侧返回 Left
,则 >>=
不会执行右侧参数。
data IOEither a = IOEither { unIOEither :: IO (Either String a) }
deriving Functor
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)
instance MonadIO IOEither where
liftIO x = IOEither (Right <$> x)
main :: IO ()
main = void $ unIOEither $ finally (IOEither (return (Left "exit")))
(liftIO (putStrLn "finalizer"))
关于haskell - 为什么 exceptT 没有 MonadMask 实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41966893/
我目前正在构建一个新的 API,它目前提供的功能之一是: inSpan :: Tracer -> Text -> IO a -> IO a 我正在寻找移动 Tracer进入一个单子(monad),给我
在上一个问题中,我问 Why is there no MonadMask instance for ExceptT? 并得到了许多令人信服的答案,包括图书馆作者,为什么不存在合法的例子。 截至 201
Edward Kmett 的异常库不提供MonadMask ExceptT 的实例. Ben Gamari once asked about this然后得出结论,文档对此进行了解释。这是我能找到的最
我是一名优秀的程序员,十分优秀!