如何更好地划分有效或无效输入

How to better partition valid or invalid inputs

给定一个可能有效或无效的输入列表,是否有一种很好的方法来转换列表但在给定一个或多个无效输入的情况下失败,并在必要时 return 有关这些无效输入的信息输入?我有这样的东西,但是感觉很不雅

def processInput(inputList: List[Input]): Try[List[Output]] = {
    inputList map { input =>
        if (isValid(input)) Left(Output(input))
        else Right(input)
    } partition { result =>
        result.isLeft
    } match {
        case (valids, Nil) => 
            val outputList = valids map { case Left(output) => output }
            Success(outputList)
        case (_, invalids) => 
            val errList =  invalids map { case Right(invalid) => invalid }
            Failure(new Throwable(s"The following inputs were invalid: ${errList.mkString(",")}")) 
    }
}

有更好的方法吗?

scalaz 的验证正是为此而设计的。尝试阅读 tale of three nightclubs 以了解其工作原理,但您的函数主体可能最终只包含类似以下内容:

def processInput(inputList: List[Input]): Validation[List[Output]] = {
  inputList foldMap { input =>
    if (isValid(input)) Failure(Output(input))
    else Success(List(input))
}

我认为您可以使用标准 Scala 大大简化您当前的解决方案:

  def processInput(inputList: List[Input]): Try[List[Output]] = 
    inputList.partition(isValid) match {
     case (valids, Nil) => Success(valids.map(Output))
     case (_, invalids) => Failure(new Throwable(s"The following inputs were invalid: ${invalids.mkString(",")}"))
  }

或者,您可以通过 scalacticOr.

获得一个非常优雅的解决方案
  import org.scalactic._

  def processInputs(inputList: List[Input]): List[Output] Or List[Input] = 
    inputList.partition(isValid) match {
     case (valid, Nil) => Good(valid.map(Output))
     case (_, invalid) => Bad(invalid)
  }

结果的类型为 org.scalactic.Or,您必须将其匹配到 GoodBad。如果你想要无效输入的列表,这种方法更有用,你可以从 Bad.

中匹配它