Scala,协变类型定义

Scala, covariant type definition

我有一组 类 继承自 Step[I, O],其中 I 是输入,O 是输出。我想定义一个不关心 I.

的更具体的子类

这是我的定义:

trait Step[I, O] {
  def apply(c:Context, i:I):Either[Error, O]
}

// H : Action handler
// A : Action handled by H
// R : Result of successful A
class Legacy[H, A <: Action[H], R](action: A with Result[R], handler: H) extends Step[Any, R] {
  override def apply(c:Context, a: Any): Either[Error, R] = {
    handler.run(action)
  }
}

但是那些 步骤 是通过 DSL 链接起来的,DSL 使用一个步骤的输出 O 作为下一个步骤的输入 I

// DSL excerpt
class AndThenBuilder[I] {
  def andThen[O](producer: (Context, I) => Step[I, O]) = ???
}

//...
val intToString:Step[Int, String] = //new SubType of Step
val legacy:Step[Any, String] = // new Legacy( action with Result[String])

//...
execute(intToString) // return AndThenBuilder[String]
 .andThen((_:Context, s:String)=>legacy)

最后一行,不编译,因为 DSL 验证类型:

Required : (Context, String) => Step[String, NotInferedO]

Found : (Context, String) => Step[Any, String]

我想将 Step[I, O] 更改为 Step[I_Or_Subtypes, O] 可以解决我的问题。但是我找不到在 StepLegacy 中定义它的语法,每次尝试都给我一个更神秘的信息。

有人可以帮助我更改我的代码,以便 Step[Any, String] 被接受为 Step[String, String]。 (我可以把Any改成其他类型)?

谢谢

so that Step[Any, String] will be accepted as a Step[String, String]

这需要第一个参数是 contra-variant,而不是标题中的协变。语法是

trait Step[-I, O] { ... }

碰巧,I可以是逆变的,但不是协变的,因为它被用作方法参数类型。虽然O可以是协变的,但不能是逆变的。