首页 > 解决方案 > yielding on exception: required Seq[MyObject] found: Seq[Product with serializable]

问题描述

I want to iterate throgh requests: Seq[Request] and run on each element a function getSingleResponse(request). Normally it yields Response(request, Some(...)) but if it fails I want it to yield Response(response, None).

With this code the returning type of getResponse don't match:

  private def getResponse(requests: Seq[Request]): Seq[Response] = {

    def getSingleResponse(request: Request) = {
      val count = getCount()
      Response(request, Some(count))
    }

    def getEmptyResponse(request: Request) = {
      Response(request, None)
    }

    for (request <- requests) yield {
      delay
      try{
        Some(getSingleResponse(request))
      } catch {
        case e: Exception => {getEmptyResponse(request)}
      }
    }
  }

Required: scala.Seq[Response]
Found: scala.collection.Seq[Product with Serializable]

标签: scala

解决方案


这是因为编译器从 (result type of block) 和 (result type of block.) 中推断出最常见的表达式超类型tryProduct with SerializableResponsecatchOption[Response]try

要使两个块的共同超类型,Response您应该省略包装getSingleResponseto的结果Some

val result: Seq[Response] = 
  for (request <- requests) yield {
    delay
    try {
      getSingleResponse(request)
    } catch {
      case e: Exception => getEmptyResponse(request)
    }
  }

来自Scala 语言规范

pt为 try 表达式的预期类型。块b应符合pt。处理程序h应符合类型 scala.PartialFunction[scala.Throwable, pt ]。try 表达式的类型是b的类型和h的结果类型的弱最小上界


此外,正如@Luis Miguel Mejía Suárez建议的那样,您可以使用scala.util.Try而不是 try 表达式:

import scala.util.Try
val result: Seq[Response] =
  for (request <- requests) yield {
    delay
    Try(getSingleResponse(request)).getOrElse(getEmptyResponse(request))
  }

推荐阅读