在SO上给出了一个解释,为什么像scalaz,cat(Scala)或Arrow(Kotlin)这样的验证不能成为monad。
据我所知,这是因为他们根据应用函子和所需的验证行为对monad进行建模,因为应用(收集所有残留物)与验证为monad的所需行为不同(序列验证和失败)第一次无效的快速)。因此,当您希望快速发生故障时,您需要将验证转换为其中一个(这是一个monad)。
在https://groups.google.com/forum/#!msg/scalaz/IWuHC0nlVws/syRUkXJklWIJ上,他们提到验证不是monad的原因,是因为以下属性不成立:
x <|*|> y === x >>= (a => y map ((a, _)))
但是看一下monad的定义,上面的属性不是monad laws的一部分。那么,这是因为monad是以应用程序的形式实现的,还是上述属性是成为monad的先决条件?
这种更高级的推理对我来说都是新的,但是由于我对FP的理解有限,我可以使用一种验证数据类型,当用作应用程序(累积invalids)时有一种行为,而另一种行为用作monad(快速失败)。
答案 0 :(得分:5)
你已经把所有的东西都搞定了。是的,Validation
的合法monad实例是可能的。问题是它会为Applicative
产生两个不同的Validation
个实例:一个累积错误,另一个从monad实例派生并快速失败。这会导致类型类不一致:程序行为取决于类型类实例的到达方式。
你提到的财产,
x <|*|> y === x >>= (a => y map ((a, _)))
可以用<|*|>
和>>=
作为map
的定义,因此可以自动保留从Monad派生的Applicative。问题是,<|*|>
的行为已经有了不同的适用性。