通用嵌套类型推断适用于 arity-2 但不适用于柯里化

Generic nested type inference works with arity-2 but not with currying

试图弄清楚为什么代码可以针对使用 arity-2 而不是柯里化的方法编译嵌套类型推断。

object Test
{
    trait Version
    object VersionOne extends Version

    trait Request[A <: Version]
    trait RequestOne extends Request[VersionOne.type]

    case class HelloWorld() extends RequestOne

    def test1[A <: Version, T <: Request[A]](t : T, a : A): T = t
    def test2[A <: Version, T <: Request[A]](t : T)(a : A): T = t
}

// This works
Test.test1(Test.HelloWorld(), Test.VersionOne)

// This doesn't
Test.test2(Test.HelloWorld())(Test.VersionOne)

test2 编译失败,出现以下错误:

Error:(22, 73) inferred type arguments [Nothing,A$A96.this.Test.HelloWorld] do not conform to method test2's type parameter bounds [A <: A$A96.this.Test.Version,T <: A$A96.this.Test.Request[A]] def get$$instance$$res1 = /* ###worksheet### generated $$end$$ */ Test.test2(Test.HelloWorld())(Test.VersionOne)

期待对此有一些见解。

Nothing in compile error 通常意味着没有推断出某些类型参数。

尝试明确指定它们

Test.test2[Test.VersionOne.type, Test.RequestOne](Test.HelloWorld())(Test.VersionOne)

test1test2 之间的区别不仅在于柯里化。例如,通常在 test2(t: ...)(a: ...) 中,a 的类型可以取决于 t 的值。所以对于 test2 类型推断比 test1.

更复杂

Multiple parameter closure argument type not inferred

What's the difference between multiple parameters lists and multiple parameters per list in Scala?

@DmytroMitin 已经解释了它失败的原因。

但是,您可以使用 Partially-Applied Type trick, together with Generalized Type Constraints.

这样解决问题
def test2[T](t: T): Test2PartiallyApplied[T] = new Test2PartiallyApplied(t)

final class Test2PartiallyApplied[T](private val t: T) extends AnyVal {
  def apply[A <: Version](a: A)(implicit ev: T <:< Request[A]): T = t
}

你可以这样使用。

Test.test2(Test.HelloWorld())(Test.VersionOne)
// res: HelloWorld = HelloWorld()