这是我上一个问题的后续。
假设我需要编写一个validate
函数,以确保给定的字符串列表由"a"、"b"和一个或多个"c"组成。
def validate(ss: List[String]): Either[NonEmptyList[MyError], Unit] = ???
假设我有三个函数来检查给定的字符串是"a"、"b"还是"c":
def validateA(str: String): Either[MyError, Unit] = ???
def validateB(str: String): Either[MyError, Unit] = ???
def validateC(str: String): Either[MyError, Unit] = ???
如何组合这些函数来实现validate
?
一种解决方案是"解析器组合器"方法。为类型Validator = Either[NonEmptyList[MyError], List[String]]
定义一个monad实例,类似于解析器组合器等oneOrMore
组合器。
我想知道是否有更简单的解决方案。
我建议你利用cats
Validated
。
如果您真的不想更改validateT
方法签名,让我们定义一些帮助程序方法:
def validateA_(str: String): ValidatedNel[MyError, Unit] = validateA(str).toValidatedNel
def validateB_(str: String): ValidatedNel[MyError, Unit] = validateB(str).toValidatedNel
def validateC_(str: String): ValidatedNel[MyError, Unit] = validateC(str).toValidatedNel
然后,您可以实现一个validate_
帮助程序函数:
import cats.data.Validated.{ invalidNel, valid }
def validate_(ss: List[String]): ValidatedNel[MyError, Unit] = ss match {
case a :: b :: c if c.nonEmpty =>
validateA_(a) combine validateB_(b) combine c.traverseU_(validateC_)
case _ => invalidNel(MyError(???)) //List too short
}
最后实现您的validate
函数为:
def validate(ss: List[String]): Either[NonEmptyList[MyError], Unit] =
validate_(ss).toEither
假设:输入列表已排序,如果它短于3
元素,则特定错误(例如列表太短(是可以接受的。
看起来你可以使用Scalactic,它允许人们在不缩短整个验证过程的情况下积累错误。
此示例看起来与您尝试执行的操作非常相似。看看吧!