我在一个重类型系统上,其中一些通用方法声明为def execute]C <: A#C](cmd: C):EitherT[Future, Fail, Seq[A#E]]
(其中A
是类上的通用类型。
这很好。但是,在测试中,当我模拟那些调用时,我必须明确键入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]
。
有人可以帮助我揭示我推理的缺陷吗?
谢谢
但是我期望它能够将
EitherT[F, SubOfA, B]
转换为EitherT[F, SubOfA.asInstanceOf[A], B]
。
保持不变就意味着不可能以这种方式“翻译”:EitherT[F, SubOfA, B]
根本不是EitherT[F, A, B]
。
现在,是一个[[separate问题是为什么尽管整个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]