验证字符串列表

时间:2017-04-04 18:40:34

标签: scala validation monads parser-combinators scala-cats

这是对我之前http://candycode.io/how-to-set-up-different-auto-layout-constraints-for-different-screen-sizes/的跟进 假设我需要编写一个函数def method_here # Other method stuff repsond_to do |format| format.js end end ,以确保给定的字符串列表包含" a"," b",以及一个或多个" ; C"

validate

假设我有三个函数来检查给定的字符串是" a"," b"还是" c":

def validate(ss: List[String]): Either[NonEmptyList[MyError], Unit] = ???

如何编写这些函数来实现def validateA(str: String): Either[MyError, Unit] = ??? def validateB(str: String): Either[MyError, Unit] = ??? def validateC(str: String): Either[MyError, Unit] = ???

一种解决方案是"解析器组合器"做法。为类型validate定义monad实例,像Validator = Either[NonEmptyList[MyError], List[String]]这样的组合器类似于解析器组合器等。

我想知道是否有更简单的解决方案。

2 个答案:

答案 0 :(得分:3)

我建议您利用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个元素,则可以接受特定错误(例如列表太短)。

答案 1 :(得分:2)

看起来您可以使用Scalactic,这样可以在不使整个验证过程短路的情况下累积错误。

example看起来与您尝试的非常相似。看看吧!