我正在尝试按顺序验证字符串列表并定义验证结果类型:
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 :(
我想让ListValidationResult
成为monad。我应该手动实施flatMap
和pure
还是有更简单的方法?
答案 0 :(得分:1)
我建议您采用完全不同的方法,利用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
根据您的示例,它可以适用于通用类型T
。
注意:
val stringList: List[String] = ???
是您要验证的字符串列表; ValidatedNel[A,B]
只是Validated[NonEmptyList[A],B]
; evaluateString
应该是您的评估功能,它目前只是一个未实现的存根if
; sequenceU
您可能需要阅读cats
相关文档:sequenceU; toEither
完全符合您的想法,将Validated[A,B]
转换为Either[A,B]
。正如@Michael指出的那样,您也可以使用traverseU
代替map
和sequenceU
val validationResult: ListValidationResult[String] =
stringList.traverseU(evaluateString).toEither