我想依次验证字符串列表和定义验证结果类型这样的:
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
一个单子。 我应该实现flatMap
和pure
手动或有更简单的方法?
我建议你采取了完全不同的方法利用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]
作为@迈克尔指出,你也可以使用traverseU
而不是map
和sequenceU
val validationResult: ListValidationResult[String] =
stringList.traverseU(evaluateString).toEither