The (<*>) = ap
exigence可以明确的术语来表示的(>>=)
:
u <*> v = u >>= \f -> fmap f v -- [1]
现在,鉴于Functor
和Applicative
实例为AccValidation
,我们有:
fmap _ (AccFailure e) = AccFailure e -- [2]
AccFailure e1 <*> AccFailure e2 = AccFailure (e1 <> e2) -- [3]
和
如果我们u = AccFailure e1
v = AccFailure e2
在[ 1],我们得到:
AccFailure e1 <*> AccFailure e2 = AccFailure e1 >>= \f -> fmap f (AccFailure e2)
代[2]和[3]成导致我们:
AccFailure (e1 <> e2) = AccFailure e1 >>= \_ -> AccFailure e2 -- [4]
的问题是,它是不可能写一个(>>=)
使得[4]成立。左侧取决于e2
值,必须在应用\_ -> AccFailure e2 :: Semigroup e => a -> AccValidation e b
时在右侧产生。但是,没有什么可以应用的 - 特别是,e1
的类型错误。 (关于这一点的进一步讨论,请参阅仙人掌答案的最后两段。)因此,没有办法给予与其Applicative
之一一致的实例AccValidation
a。
你想象什么情况?请注意,'Either'的应用实例在非错误端进行累加。 – Alec
如果早期阶段失败,则不能在稍后的“阶段”中运行。使用Applicative,即使您不能将它们应用于获得成功的结果(因此您可以知道后面的阶段的计算是否失败),您仍然可以*计算*后面的阶段。随着Monad,每个阶段都会返回下一个阶段,所以你甚至不知道后面的阶段应该是什么。 – immibis
@Alec适用于'Either'并不会“积累”*在所有方面*与AccValidation积累的意义相同,对吗? –