通用嵌套类型推断适用于 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)
test1
和 test2
之间的区别不仅在于柯里化。例如,通常在 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()
试图弄清楚为什么代码可以针对使用 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)
test1
和 test2
之间的区别不仅在于柯里化。例如,通常在 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()