通用嵌套类型推断适用于arity-2,但不适用于curring

时间:2019-06-13 16:55:04

标签: scala generics currying

试图弄清楚为什么代码对使用arity-2而不是使用currying的方法进行嵌套类型推断的编译。

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无法编译,并出现以下错误:

  

错误:(22,73)推断的类型参数[Nothing,A $ A96.this.Test.HelloWorld]不符合方法test2的类型参数范围[A <:A $ A96.this.Test.Version,T <:A $ A96.this.Test.Request [A]   def get $$ instance $$ res1 = / * ### worksheet ###生成$$ end $$ * / Test.test2(Test.HelloWorld())(Test.VersionOne)

期待对此有一些见识。

2 个答案:

答案 0 :(得分:1)

Nothing出现编译错误通常表示未推断某些类型参数。

尝试明确指定它们

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

test1test2之间的区别不仅在于汇率。例如,通常test2(t: ...)(a: ...)的{​​{1}}类型可以取决于a的值。因此,对于t,类型推断要比test2复杂。

Scala type inference and multiple arguments list

Type inference with type aliases and multiple parameter list function

Multiple parameter closure argument type not inferred

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

答案 1 :(得分:1)

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

但是,您可以使用Partially-Applied Type技巧和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()