1

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

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(",")}")) 
    }
}

有一个更好的方法吗?

4

2 回答 2

2

scalaz 的验证正是为此而设计的。尝试阅读三个夜总会的故事,了解它是如何工作的,但你的函数体最终可能只包含以下内容:

def processInput(inputList: List[Input]): Validation[List[Output]] = {
  inputList foldMap { input =>
    if (isValid(input)) Failure(Output(input))
    else Success(List(input))
}
于 2015-04-14T04:30:21.480 回答
2

我认为您可以使用标准 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(",")}"))
  }

或者,您可以使用scalactic's获得一个非常优雅的解决方案Or

  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)
  }

结果是 type org.scalactic.Or,然后您必须将其匹配到Goodor Bad。如果您想要无效输入的列表,这种方法更有用,您可以将其从Bad.

于 2015-04-14T10:57:40.250 回答