6

让我们假设一个使用构建器模式构造的对象。

此构建器模式将包含一个build专注于字段验证然后转换为目标类型的方法。

可以使用以下方式实现此验证:

  • Either[FailureObject, TargetObject]类型
  • Try[TargetObject](Scala 2.10 的新功能)
  • Validation[FailureObject, TargetObject]ValidationNEL[FailureObject, TargetObject]来自 scalaz 库

Validation我读到过Either类型的主要优点之一是Validation可以“开箱即用”累积故障。

但是“新”Try方式呢?我注意到它Try也有开箱即用的“单子”方法,比如mapflatMap等等......在没有Projection.

因此,我想每个字段验证方法都返回 a Try[FieldType],更准确地说,如果出现任何故障, a Try[SpecificFieldExceptionType]; 这个嵌套的包含一个Stringmessage 字段和一个 rootCause 字段,可以在整个build方法中累积。

使用 Scala 2.10,是否可以或应该Try练习替换 scalaz 验证库以进行简单的验证,如构建器模式所涉及的?

**编辑* ***

通过阅读Try源代码,听起来Try无法累积多个异常,因此面向快速失败。EvenTry.flatMap返回潜在的先前失败,因此没有累积的概念:

def flatMap[U](f: T => Try[U]): Try[U] = this.asInstanceOf[Try[U]]

相反ValidationNEL,处理累积功能。

有什么确认吗?

4

1 回答 1

11

有权衡:

  • scalaz.Validation能够累积E给定Semigroup[E]实例的类型错误。它旨在用作Applicative,例如:

    (fragileFoo |@| fragileBar) { case (foo, bar) => doSomething(foo, bar) }
    

    它确实有mapflatMap方法,偏向于Success侧面,所以你可以方便地在for理解中使用它。但是,没有Monad为它定义实例,所以它不能用于任何高阶的东西(例如,你不能将它与 monad 转换器一起使用)。不过,这个缺点对你来说似乎不是问题。

  • scalaz.\/,你没有提到,确实形成了Monad(同样,偏向Right一边)。但是当用作 时Applicative,它不会像以前那样累积失败Validation

  • util.Try类似scalaz.\/,专门用于Throwable。尽管它再次缺乏错误的累积,但它确实具有错误恢复的概念。但是,对于您的“构建器模式”用例,这似乎不是非常有用。

  • 最后,util.Either与其他三个选项相比,不值得考虑:因为它不偏向一侧或另一侧,所以每次你想做一元的事情时,你都必须明确且一致地要求leftor投影。right

我最好的猜测是,对于你的情况,scalaz.Validation是最合适的选择。

于 2013-04-30T05:15:52.327 回答