“(<*>)= ap”适用/单子法则与这两个类之间的关系到底如何?

jbe*_*man 5 monads haskell applicative

ap没有文档说明的规范,请阅读并指出可能是的注释<*>,但这并不是出于实际原因:

ap                :: (Monad m) => m (a -> b) -> m a -> m b
ap m1 m2          = do { x1 <- m1; x2 <- m2; return (x1 x2) }
-- Since many Applicative instances define (<*>) = ap, we
-- cannot define ap = (<*>)
Run Code Online (Sandbox Code Playgroud)

所以我承担ap(<*>) = ap法律是简写“AP的右手边”,实际上法律表达之间的关系>>=return以及<*>对不对?否则,法律将毫无意义。

我正在考虑上下文Validation,并且似乎没有合法的Monad实例是多么令人不满意。我也在考虑ApplicativeDo,以及这种转换如何使我们从Monad实例的实际效果中恢复Validation;我最常想做的是尽可能地累积错误,但在必要时仍然能够使用bind。实际上bindV,我们导出了几乎在所有地方都需要使用的功能,这很荒谬。我能想到的唯一的实际后果是,我们会根据所使用的合成类型(或程序在理论上如何通过重写规则来转换)来累积不同或更少的错误,尽管我不确定为什么应用合成会转换为单子)。

编辑:在相同法律的文档Monad是更广泛:

此外,Monad操作和应用操作应与以下内容相关:

pure = return
(<*>) = ap
Run Code Online (Sandbox Code Playgroud)

上述法律暗示:

fmap f xs  =  xs >>= return . f
(>>) = (*>)
Run Code Online (Sandbox Code Playgroud)

“上述法律意味着”……那么这里是否是我们真正关心的真正法律的想法?

但是现在我离开试图在的上下文中了解这些Validation。第一条定律将成立。如果我们仅定义,第二个显然可以成立(>>) = (*>)

但是Monad令人惊讶的是,该文档并未说明>>应如何关联(除非我只是想念它)。大概我们想要那个

a >> b = a >>= \_ -> b
Run Code Online (Sandbox Code Playgroud)

...并且(>>)包含在类中,以便可以提高效率,而这从来没有完全纳入文档中。

所以,如果这是的话,那么我想办法MonadApplicative相关居然是这样的:

return = pure
xs >>= return . f = fmap f xs
a >>= \_ -> b = fmap (const id) a <*> b
Run Code Online (Sandbox Code Playgroud)

use*_*038 3

每个Monad都会产生一个Applicative,并且对于该诱导的Applicative<*> = ap将定义地成立。但是给定两个结构 -Monad m和- 如果没有两个定律和 ,Applicative m则不能保证这些结构一致。例如,采用列表的“常规”实例和 zip-list实例。虽然与实例不一致从根本上来说并没有什么“错误” ,但它可能会让大多数用户感到困惑,因此法律禁止这样做。<*> = appure = returnMonadApplicativeMonadApplicativeMonad

tl;dr 所讨论的法律旨在确保这一点,MonadApplicative以直观明显的方式达成一致。