如何使它成为monad?

时间:2017-04-04 15:47:18

标签: scala monad-transformers scala-cats

我正在尝试按顺序验证字符串列表并定义验证结果类型:

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。我应该手动实施flatMappure还是有更简单的方法?

1 个答案:

答案 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代替mapsequenceU

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