1

I am trying to validate a list of strings sequentially and define the validation result type like that:

import cats._, cats.data._, cats.implicits._

case class ValidationError(msg: String)
type ValidationResult[A] =  Either[NonEmptyList[ValidationError], A]
type ListValidationResult[A] = ValidationResult[List[A]] // not a monad :(

I would like to make ListValidationResult a monad. Should I implement flatMap and pure manually or there is an easier way ?

Michael
  • 41,026
  • 70
  • 193
  • 341

1 Answers1

1

I suggest you to take a totally different approach leveraging cats Validated:

import cats.data.Validated.{ invalidNel, valid }

val stringList: List[String] = ???

def evaluateString(s: String): ValidatedNel[ValidationError, String] =
  if (???) valid(s) else invalidNel(ValidationError(s"invalid $s"))

val validationResult: ListValidationResult[String] = 
  stringList.map(evaluateString).sequenceU.toEither

It can be adapted for a generic type T, as per your example.


Notes:

  • val stringList: List[String] = ??? is the list of strings you want to validate;
  • ValidatedNel[A,B] is just a type alias for Validated[NonEmptyList[A],B];
  • evaluateString should be your evaluation function, it is currently just an unimplemented stub if;
  • sequenceU you may want to read cats documentation about it: sequenceU;
  • toEither does exactly what you think it does, it converts a Validated[A,B] to an Either[A,B].

As @Michael pointed out, you could also use traverseU instead of map and sequenceU

val validationResult: ListValidationResult[String] = 
  stringList.traverseU(evaluateString).toEither
Federico Pellegatta
  • 3,977
  • 1
  • 17
  • 29
  • 1
    Oh, thanks. I forgot about it. It's possible to use `traverse` (or `traverseU`) instead of `map` and `sequence` (`sequenceU`). – Michael Apr 04 '17 at 17:56
  • I need to clarify my question: suppose I need to make sure that the input `"a"`, `"b"`, and `one of more "c"`. Suppose you three functions: `String => ValidatedNel[ValidationError, String]` to check if a given string is "a", "b", or "c". How would you validate a list ? – Michael Apr 04 '17 at 18:03
  • I will probably write another question about it. – Michael Apr 04 '17 at 18:17
  • see my new question : http://stackoverflow.com/questions/43215145/validating-list-of-strings – Michael Apr 04 '17 at 18:51