如何创建一个 Either[S,T],其中 S 或 T 可以是 Unit?

How to create an Either[S,T] where S or T could be Unit?

private def responseValidationFlow[T](responsePair: ResponsePair)(implicit evidence: FromByteStringUnmarshaller[T]) = responsePair match {
    case (Success(response), _) => {
      response.entity.dataBytes
        .via(Framing.delimiter(ByteString("\n"), maximumFrameLength = 8192))
        .mapAsyncUnordered(Runtime.getRuntime.availableProcessors()) { body =>
          if (response.status == OK) {
            val obj: Future[T] = Unmarshal(body).to[T]
            obj.foreach(x => log.debug("Received {}: {}.", x.getClass.getSimpleName, x))
            obj.map(Right(_))
          } else {
            val reason = body.utf8String
            log.error("Non 200 response status: {}, body: {}.", response.status.intValue(), reason)
            Future.successful(reason)
              .map(Left(_))
          }
        }
    }
    case (Failure(t), _) => {
      Source.single(Left(t.getMessage))
    }
  }

我想做的是参数化 Either 的两边。这并不难,但我遇到的麻烦是创建一个没有值的 LeftRight。在这种情况下,body 应该被完全消耗并丢弃。我尝试使用 ClassTags,但编译器认为类型是 Any,而不是 ST。此方法的示例调用看起来像 responseValidationFlow[String, Unit] 生成 Source[Either[String, Unit]]

我相信,您可以在范围内为 Unit 定义一个隐式解组器:

implicit val unitUnmarshaller: FromByteStringUnmarshaller[Unit] = 
  Unmarshaller.strict(_ => ())

根据@Kolmar 的建议,这里是工作代码。

private def responseValidationFlow[L, R](responsePair: ResponsePair)(
  implicit ev1: FromByteStringUnmarshaller[L], ev2: FromByteStringUnmarshaller[R]
): Source[Either[L, R], Any] = {
  responsePair match {
    case (Success(response), _) => {
      response.entity.dataBytes
        .via(Framing.delimiter(ByteString("\n"), maximumFrameLength = 8192))
        .mapAsyncUnordered(Runtime.getRuntime.availableProcessors()) { body =>
          if (response.status == OK) {
            val obj: Future[R] = Unmarshal(body).to[R]
            obj.foreach(x => log.debug("Received {}.", x.getClass.getSimpleName))
            obj.map(Right(_))
          } else {
            log.error("Non 200 response status: {}.", response.status.intValue())
            Unmarshal(body).to[L]
              .map(Left(_))
          }
        }
    }
    case (Failure(t), _) => {
      log.error(t, "Request failed.")
      Source.empty
    }
  }
}

如果像这样调用方法 responseValidationFlow[Status, Unit],那么 FromByteStringUnmarshaller[Unit] 在调用站点可用。编译器使用 implicit 证据来查找所需的 Unmarshaller.