我在阅读有关Monad变压器的文章,发现这篇看似广为人知的文章-Monad Transformers的温和介绍。引起我注意的是作者在其中描述了一个临时ExceptT
变压器的适用实例,但留下警告说该实例不合法。
这是代码:
data EitherIO e a = EitherIO {
runEitherIO :: IO (Either e a)
}
instance Functor (EitherIO e) where
fmap f = EitherIO . fmap (fmap f) . runEitherIO
instance Applicative (EitherIO e) where
pure = EitherIO . return . Right
f <*> x = EitherIO $
liftA2 (<*>)
(runEitherIO f)
(runEitherIO x)
和警告:
警告:非常有远见的读者向我指出,这种适用性实例是非法的。具体地说,它无条件地执行了右侧的副作用。对合法实例的期望是,只有在左侧操作成功的情况下,才应执行右侧的副作用。
我假设具体是实施<*>
的问题。
因此,我的主要问题是:该实例不符合哪些法律?
据我所知,这四个适用法则都得到了满足(我当然可能错了)。作者说,问题在于,<*>
即使左侧操作不成功(我假设“成功操作”也意味着IO),也会执行右侧的副作用(我假设位于的右侧)Right
执行时将产生一个值)。
从使用的角度来看,虽然我认为这很有意义,但仍然可以从中看出哪些法律不完全符合要求以及为什么不符合要求。
另外,为什么实例不合法的解释提到了副作用,这使得推理类型仅适用于IO monad?但是,在本文的最后,作为最后的一步,我们将IO monad更改为常规monad,并使其成为所描述数据类型的参数。这就引出了另一个问题:如果我们想象自己是在写这个monad转换器,那么我需要运用什么样的推理才能注意到所描述的应用实例确实是非法的,而无需诉诸于可能是特定的monad的情况。用这个变压器吗?
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句