小编Dmi*_*try的帖子

为什么这个适用的实例是非法的?

我正在阅读有关monad变形金刚的文章,并发现这篇着名的文章 - "Monad变形金刚的温柔介绍".引起我注意的是作者描述临时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)
Run Code Online (Sandbox Code Playgroud)

警告:

警告:一位非常敏锐的读者向我指出,这个适用的例子是非法的.具体而言,它无条件地执行右侧的副作用.合法实例的期望是,如果左侧是成功的操作,它应该只执行右侧的副作用.

我假设具体实施<*>是问题.

所以我的主要问题是:这个例子确实不符合哪些法律?

从我所看到的,四个适用法律得到满足(当然我可能是错的).作者说,问题是右边的副作用(我假设,右边<*>)是执行的,即使左侧不是一个成功的操作(我假设,"成功操作"意味着IO动作Right在执行时会产生一个值).

虽然从使用的角度来看,我认为这是有道理的,但是看看哪些法律在这里不满意,以及为什么这样做仍然是有启发性的.

此外,对实例非法的原因的解释提到了副作用,这使得推理类型仅适用于IO monad?但是在文本的最后,作为一个结束动作,我们将IO monad更改为一般monad并使其成为所描述数据类型的参数.这引出了另一个问题:如果我们想象自己正在编写这个monad变换器,我需要应用什么样的推理,注意所描述的应用实例确实是非法的,而不需要考虑可能的特定monad用这个变压器?

haskell applicative

7
推荐指数
1
解决办法
138
查看次数

标签 统计

applicative ×1

haskell ×1