Scala 类型系统,无法找到内联的共同祖先
Scala type system, cannot find common ancestor inline
我在一个重类型系统上,其中一些泛型方法声明为 def execute]C <: A#C](cmd: C):EitherT[Future, Fail, Seq[A#E]]
(其中 A
是 class 上的泛型类型。
这很好用。但是在我的测试中,当我模拟这些调用时,我必须明确键入 Fail
和 A#E
的超类型,否则我的代码无法编译。
// Event is the base type of Receiver#E
val event:Event = SubOfEvent()
handler.execute(any[SubOfCommand]) returns Seq(event).asRightT[Future, Fail]
val fail:Fail = SubOfFail()
handler.execute(any[SubOfCommand]) returns fail.asLeftT[Future, Seq[Receiver#E]]
如果我内联 event
或 fail
的声明,我有 类型不匹配:
found : cats.data.EitherT[scala.concurrent.Future,SubOfFail,scala.collection.immutable.Seq[SubOfEvent]]
required: cats.data.EitherT[scala.concurrent.Future,Fail,scala.collection.immutable.Seq[Receiver#E]]
(which expands to) cats.data.EitherT[scala.concurrent.Future,Fail,scala.collection.immutable.Seq[Event]]
Note: SubOfFail <: Fail, but class EitherT is invariant in type A.
You may wish to define A as +A instead. (SLS 4.5)
handler.execute(any[SubOfCommand]) returns SubOfFail().asLeftT[Future,
^
我理解关于 EitherT
在类型 A
中不变的信息。但我期待它能够将 EitherT[F, SubOfA, B]
翻译为 EitherT[F, SubOfA.asInstanceOf[A], B]
.
有人可以帮我揭露我推理中的缺陷吗?
谢谢
But I was expecting it to be able to translate EitherT[F, SubOfA, B]
as EitherT[F, SubOfA.asInstanceOf[A], B]
.
不变性恰恰意味着不可能 "translate" 这种方式:EitherT[F, SubOfA, B]
根本不是 EitherT[F, A, B]
。
现在,一个 单独的 问题是为什么 fail
的类型没有被推断为 Fail
尽管整个 fail.asLeftT[Future, Seq[Receiver#E]]
。答案是 Scala 类型推断不能那样工作;当键入 expression.method(...)
时,它将首先键入 expression
,并且不能使用 method
.
的预期 return 类型
您仍然可以内联编写它们,但您需要类型归属:
(SubOfFail(): Fail).asLeftT[Future, Seq[Receiver#E]]
在 Seq
的情况下,显式类型参数也可以工作:
Seq[Event](SubOfEvent()).asRightT[Future, Fail]
我在一个重类型系统上,其中一些泛型方法声明为 def execute]C <: A#C](cmd: C):EitherT[Future, Fail, Seq[A#E]]
(其中 A
是 class 上的泛型类型。
这很好用。但是在我的测试中,当我模拟这些调用时,我必须明确键入 Fail
和 A#E
的超类型,否则我的代码无法编译。
// Event is the base type of Receiver#E
val event:Event = SubOfEvent()
handler.execute(any[SubOfCommand]) returns Seq(event).asRightT[Future, Fail]
val fail:Fail = SubOfFail()
handler.execute(any[SubOfCommand]) returns fail.asLeftT[Future, Seq[Receiver#E]]
如果我内联 event
或 fail
的声明,我有 类型不匹配:
found : cats.data.EitherT[scala.concurrent.Future,SubOfFail,scala.collection.immutable.Seq[SubOfEvent]]
required: cats.data.EitherT[scala.concurrent.Future,Fail,scala.collection.immutable.Seq[Receiver#E]]
(which expands to) cats.data.EitherT[scala.concurrent.Future,Fail,scala.collection.immutable.Seq[Event]]
Note: SubOfFail <: Fail, but class EitherT is invariant in type A.
You may wish to define A as +A instead. (SLS 4.5)
handler.execute(any[SubOfCommand]) returns SubOfFail().asLeftT[Future,
^
我理解关于 EitherT
在类型 A
中不变的信息。但我期待它能够将 EitherT[F, SubOfA, B]
翻译为 EitherT[F, SubOfA.asInstanceOf[A], B]
.
有人可以帮我揭露我推理中的缺陷吗?
谢谢
But I was expecting it to be able to translate
EitherT[F, SubOfA, B]
asEitherT[F, SubOfA.asInstanceOf[A], B]
.
不变性恰恰意味着不可能 "translate" 这种方式:EitherT[F, SubOfA, B]
根本不是 EitherT[F, A, B]
。
现在,一个 单独的 问题是为什么 fail
的类型没有被推断为 Fail
尽管整个 fail.asLeftT[Future, Seq[Receiver#E]]
。答案是 Scala 类型推断不能那样工作;当键入 expression.method(...)
时,它将首先键入 expression
,并且不能使用 method
.
您仍然可以内联编写它们,但您需要类型归属:
(SubOfFail(): Fail).asLeftT[Future, Seq[Receiver#E]]
在 Seq
的情况下,显式类型参数也可以工作:
Seq[Event](SubOfEvent()).asRightT[Future, Fail]