为什么验证会违反 monad 法则?

Why would validation break the monad laws?

SO 解释了为什么像 scalaz、cats (Scala) 或 Arrow (Kotlin) 中的验证不能是 monad。

据我所知,这是因为他们根据应用仿函数对 monad 进行了建模,并且作为应用的验证的期望行为(收集所有无效项)不同于作为 monad 的验证的期望行为(序列验证)并在第一个无效时快速失败)。因此,当您想要快速失败时,您需要将验证转换为 either(这是一个 monad)。

https://groups.google.com/forum/#!msg/scalaz/IWuHC0nlVws/syRUkXJklWIJ 上,他们提到验证不是 monad 的原因,是因为以下 属性 不成立:

x <|*|> y === x >>= (a => y map ((a, _))) 

但是查看 monad 的定义,上面的 属性 不是 monad laws 的一部分。那么,这是 monad 是根据应用程序实现的结果,还是上述 属性 成为 monad 的先决条件?

这种更高级的推理对我来说是全新的,但在我对 FP 的有限理解中,我可以有一个验证数据类型,当用作应用程序时(累积无效值)具有一种行为,而当用作应用程序时具有另一种行为用作 monad(快速失败)。

你已经答对了所有的部分。是的,Validation 的合法 monad 实例是可能的。问题是它会为 Validation 产生两个不同的 Applicative 实例:一个累积错误,另一个从 monad 实例派生并快速失败。这将导致类型类不连贯:程序行为取决于类型类实例是如何到达的。

你提到的属性,

x <|*|> y === x >>= (a => y map ((a, _)))

可以作为 <|*|>>>=map 方面的定义,因此自动适用于从 Monad 派生的 Applicative。问题是已经有一个不同的 Applicative 具有不同的 <|*|>.

行为