如何使它成为一个单子?(How to make it a monad?)

2019-09-29 08:15发布

我想依次验证字符串列表和定义验证结果类型这样的:

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一个单子。 我应该实现flatMappure手动或有更简单的方法?

Answer 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]

作为@迈克尔指出,你也可以使用traverseU而不是mapsequenceU

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


文章来源: How to make it a monad?