【问题标题】:Validating list of strings验证字符串列表
【发布时间】:2017-08-30 02:54:07
【问题描述】:

这是我之前的question 的后续。
假设我需要编写一个函数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 这样的组合器类似于解析器组合器等。

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

【问题讨论】:

  • 它们是否已排序?您可以依靠职位来进行验证吗? (例如,第一个必须是a,第二个必须是b,然后是一个或多个c
  • 可以使用 ADT 代替 Unit 吗?为您的问题提供一个提示,使用函数orElse

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


【解决方案1】:

看起来您可以使用Scalactic,它允许累积错误而不会使整个验证过程短路。

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

【讨论】:

  • 感谢您的建议!没听说过这个库。
  • 不客气。我希望这就是你要找的。​​span>
【解决方案2】:

我建议你利用catsValidated

如果您真的不想更改 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 元素短,则可接受特定错误(例如列表太短)。

【讨论】:

  • 谢谢!恐怕这个解决方案不够通用。如果我需要检查列表是否由one or more aone or more b 组成?
猜你喜欢
  • 1970-01-01
  • 2016-03-19
  • 1970-01-01
  • 2016-10-10
  • 2014-07-29
  • 1970-01-01
  • 2017-11-27
  • 2011-02-21
相关资源
最近更新 更多