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
,因为在某些以前的版本中物化值并不重要,但这仍然没有给我关于如何解决我的问题的线索。
中的示例类似
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 => Y
在 Y
中是协变的,但在 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]]]]
.)
我有一个构建在 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
,因为在某些以前的版本中物化值并不重要,但这仍然没有给我关于如何解决我的问题的线索。
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 => Y
在 Y
中是协变的,但在 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]]]]
.)