Reputation: 8281
I have written a combinator to convert a ValidationNel[A, List[B]]
into ValidationNel[A, NonEmptyList[B]]
that returns a Failure
when the List
is empty.
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]]
}
Is there a better way ?
Upvotes: 0
Views: 159
Reputation: 9820
We can improve your nonEmpty
function in two ways :
List
into an Option[NonEmptyList]
using
toNel
.ValidationNel
is similar to a flatMap
, but Validation
doesn't have a flatMap
operation since it is an Applicative and not a Monad. Scalaz provides some easy functions to convert between Validation
and \/
(also known as disjunction), so we can use \/
's flatMap
.Your nonEmpty
function then could look like :
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
Which you could use as :
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))
Upvotes: 2