将ValidationNel [A,List [B]]转换为ValidationNel [A,NonEmptyList [B]]

时间:2015-12-22 20:39:45

标签: scala scalaz

我编写了一个组合器,将ValidationNel[A, List[B]]转换为ValidationNel[A, NonEmptyList[B]],当Failure为空时返回List

  def nonEmpty[A, B](valid : ValidationNel[A, List[B]], fail : => A) : ValidationNel[A, NonEmptyList[B]] =
    valid match {
      case Failure(f) => f.failure[NonEmptyList[B]]
      case Success(s) =>
        if (!s.isEmpty) NonEmptyList(s.head, s.tail:_*).successNel[A]
        else fail.failureNel[NonEmptyList[B]]
    }

有更好的方法吗?

1 个答案:

答案 0 :(得分:2)

我们可以通过两种方式改进您的nonEmpty功能:

  • Scalaz可以使用List转换为Option[NonEmptyList] toNel
  • ValidationNel上的模式匹配与flatMap类似,但Validation没有flatMap操作,因为它是 Applicative < / em>而不是 Monad 。 Scalaz提供了一些简单的函数来转换Validation\/(也称为析取),因此我们可以使用\/&#39; s flatMap

您的nonEmpty功能可能如下所示:

import scalaz.{ValidationNel, NonEmptyList}
import scalaz.syntax.std.list._
import scalaz.syntax.std.option._
import scalaz.syntax.nel._

def nonEmpty[A, B](valid: ValidationNel[A, List[B]], 
                   fail: => A): ValidationNel[A, NonEmptyList[B]] =
  valid.disjunction.flatMap(_.toNel toRightDisjunction fail.wrapNel).validation

您可以将其用作:

import scalaz.syntax.validation._

nonEmpty(List(1,2).success, "test")
// scalaz.ValidationNel[String,scalaz.NonEmptyList[Int]] = 
//   Success(NonEmptyList(1, 2))

nonEmpty(List().success, "list is empty")
// scalaz.ValidationNel[String,scalaz.NonEmptyList[Nothing]] =
//   Failure(NonEmptyList(list is empty))