Source[T, _] 和 Source[T, NotUsed] 有什么区别?

What is the difference between Source[T, _] and Source[T, NotUsed]?

我有一个构建在 Play/Lagom 堆栈之上的应用程序。我需要调用一项服务,该服务需要 Source[T, NotUsed] 将文件流式传输到它。这是服务的界面:

def foo(fooId: UUID): ServiceCall[Source[ByteString, NotUsed], Source[String, NotUsed]]

因此,我通过以下方式使用 Play 文档中的 Accumulator.source

  private def doSomething(fooId: UUID): BodyParser[Future[Seq[String]]] = BodyParser { _ =>
    Accumulator.source[ByteString]
      .mapFuture { source: Source[ByteString, NotUsed] =>
        externalService
          .foo(fooId)
          .invoke(source)
          .map { x =>
            Right(x.runWith(Sink.seq[String]))
          }
      }
  }

现在,在 mapFuture 调用中,source 的类型是 Source[ByteString, _],但如果我将其更改为 Source[ByteString, NotUsed] 以调用服务,如在上面的示例中,我在 IDE 中收到错误 Source[ByteString, _] 是预期的。 _ 不应该意味着我可以将类型更改为我想要的任何类型,包括 NotUsed 吗?另一方面,这两者在语义上不应该是等价的吗?我发现 Akka 团队引入了 akka.NotUsed 来替换 Unit,因为在某些以前的版本中物化值并不重要,但这仍然没有给我关于如何解决我的问题的线索。

以上代码段与 Play documentation on directing the body elsewhere.

中的示例类似

On the other hand, shouldn't these two be semantically equivalent anyway?

没有。它们不等价,因为一个是另一个的子类型,反之亦然。

Source[ByteString, NotUsed]Source[ByteString, _] 的子类型。并且因为 Source 是协变的 Source[ByteString, _]Source[ByteString, Any].

相同
implicitly[Source[ByteString, NotUsed] <:< Source[ByteString, _]]
implicitly[Source[ByteString, _] =:= Source[ByteString, Any]]
implicitly[Source[ByteString, Any] =:= Source[ByteString, _]]

Accumulator.source[ByteString]has type Accumulator[ByteString, Source[ByteString, _]]. .mapFuture(..) acceptsSource[ByteString, _] => Future[B]。由于 X => YY 中是协变的,但在 X 中是逆变的 Source[ByteString, _] => Future[B]Source[ByteString, NotUsed] => Future[B])

的子类型
implicitly[(Source[ByteString, _] => Future[B]) <:< (Source[ByteString, NotUsed] => Future[B])]

因此您可以使用 Source[ByteString, _] => Future[B] 而不是 Source[ByteString, NotUsed] => Future[B],反之亦然。

(B 好像是 Future[Either[Result, Future[Seq[String]]]].)

https://docs.scala-lang.org/tour/variances.html