如何使它成为一个单子?
How to make it a monad?
我正在尝试按顺序验证字符串列表并定义验证结果类型:
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
还是有更简单的方法?
我建议您采用完全不同的方法利用 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
我正在尝试按顺序验证字符串列表并定义验证结果类型:
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
还是有更简单的方法?
我建议您采用完全不同的方法利用 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