`(< *>)= ap` Applicative / Monad法究究如何将这两个类联系起来?

时间:2017-10-24 14:40:53

标签: haskell monads 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 = (<*>)

所以我假设ap法律中的(<*>) = ap是&#34; ap&#34;右边的简写。法律实际上表达了>>=return<*>之间的关系吗?否则法律毫无意义。

上下文是我在考虑Validation以及它似乎有一个合法的Monad实例是多么令人不满意。我也在考虑ApplicativeDo以及这种转变如何让我们从Monad实例对Validation的实际效果中恢复过来;我最常想做的是尽可能地累积错误,但仍然能够在必要时使用bind。我们实际上导出了bindV函数,我们需要在任何地方使用它,这都是荒谬的。我能想到无法无天的唯一实际后果是,我们根据我们使用的构成类型(或者我们的程序在理论上如何通过重写规则进行转换)积累不同或更少的错误,尽管我不确定为什么应用组合会永远转变为monadic)。

编辑Monad中相同法律的文档更为广泛:

  

此外,Monad和Applicative操作应该如下:

pure = return
(<*>) = ap
     

上述法律意味着:

fmap f xs  =  xs >>= return . f
(>>) = (*>)

&#34;上述法律意味着......这里的想法是,这些是我们关心的真正法律吗?

但是现在我在Validation的背景下试图理解这些。第一部法律将成立。如果我们只定义(>>) = (*>),显然可以保留第二个。

但是Monad的文档令人惊讶地说明了>>应该如何关联的任何事情(除非我只是错过了)。大概我们想要那个

a >> b = a >>= \_ -> b

...并且(>>)包含在类中,以便可以覆盖它以提高效率,而这从未完全进入文档。

所以如果那个的情况,那么我猜MonadApplicative关联的方式实际上是这样的:

return = pure
xs >>= return . f = fmap f xs
a >>= \_ -> b = fmap (const id) a <*> b

2 个答案:

答案 0 :(得分:4)

  

因此,我认为ap法律中的(<*>) = ap是&{34; ap&#34;右侧的缩写。法律实际上表达了>>=return<*>之间的关系吗?

     

在我看来(<*>) = ap并不严格意味着任何事情(至少在AMP之后)。据推测,它试图在<*>ap的右侧之间表达某种关系。也许我是迂腐的。

讽刺地说,我说的恰恰相反:因为ap位于definitionally equal的右侧,说(<*>) = apm1 <*> m2 = do { x1 <- m1; x2 <- m2; return (x1 x2) }完全相同}。这只是处理这种平等的正常的第一步:扩展定义。

回复评论:

  

是的,但定义可以自由更改。

然后法律也会改变或被删除。就像将join添加到Monad时一样,当前的定义将成为法律。

  

根本不可能将其定义为ap = <*>

你是说用这种方式定义ap或法律是不可能的?

如果ap,那么你是对的:它的类型错误。但是说这样的法律会很好。

答案 1 :(得分:4)

每个Monad都会产生一个Applicative,对于诱导Applicative的{​​{1}},<*> = ap将会定义。但鉴于两个结构 - Monad mApplicative m - 如果没有两个法律<*> = appure = return,则无法保证这些结构一致。例如,选择&#39;常规&#39;列表的Monad实例和zip-list Applicative实例。虽然没有什么从根本上是错误的&#39;关于MonadApplicative实例的不同意见,它可能会让大多数用户感到困惑,因此Monad法律禁止这样做。

tl; dr相关法律旨在确保MonadApplicative以直观明显的方式达成一致。