为什么 Scala 编译器不接受这个 lambda 作为参数?
Why doesn't the Scala compiler accept this lambda as a parameter?
假设我有一个 Thing
:
的接口
abstract class Thing[A](a_thing: A) {
def thingA = a_thing
}
我按如下方式实现 Thing
:
class SpecificThing(a: String) extends Thing[String](a)
此外,假设我有一个函数,它接受一个 Thing
和一个对 Thing
做某事的 lambda 作为参数:
def doSomething[A](fn: Thing[A] => A, t: Thing[A]) : A = fn(t)
现在,让我们使用这些东西:
val st = new SpecificThing("hi")
val fn1: (Thing[String]) => String = (t: Thing[String]) => { t.thingA }
println(doSomething(fn1, st))
这会打印 hi
。到目前为止,一切都很好。但是我比较懒,不喜欢打那么多,所以我把程序改成下面这样:
type MyThing = Thing[String]
val st = new SpecificThing("hi")
val fn2: (MyThing) => String = (t: MyThing) => { t.thingA }
println(doSomething(fn2, st))
这也打印 hi
。极好!编译器可以分辨出 SpecificThing
既是 Thing[String]
又是 MyThing
。但是这个案例呢?
val st = new SpecificThing("hi")
val fn3: (SpecificThing) => String = (t: SpecificThing) => { t.thingA }
println(doSomething(fn3, st))
现在我得到:
Error:(14, 23) type mismatch;
found : SpecificThing => String
required: Thing[?] => ?
println(doSomething(fn3, st))
^
这是怎么回事?什么是 Thing[?]
?
f3
不是 Thing[String] => String
,而是 SpecificThing => String
。例如,为什么它们不兼容:
class SpecificThing2 extends Thing[String] {
def thingB = 2.0
}
val f4: SpecificThing2 => String = {
st: SpecificThing2 => f"%f${st.thingB / 3.0}"
}
val t = new Thing[String]("haha"){}
f4(t) // would be an error when f4 tried to access t.thingB
更正式地说,Function1
在其第一个类型参数 Function1[-T, +R]
.
中是 逆变
一个Thing[?]
就是这个样子;它是某种未知类型 X
的 Thing[X]
。编译器正在大胆地尝试推断类型 A
应该是什么,但它无法使其工作:它需要一个 Thing[A] => A
用于某些(未知的)类型 A
,并且您将其传递给 SpecificThing => String
;那是错误。
假设我有一个 Thing
:
abstract class Thing[A](a_thing: A) {
def thingA = a_thing
}
我按如下方式实现 Thing
:
class SpecificThing(a: String) extends Thing[String](a)
此外,假设我有一个函数,它接受一个 Thing
和一个对 Thing
做某事的 lambda 作为参数:
def doSomething[A](fn: Thing[A] => A, t: Thing[A]) : A = fn(t)
现在,让我们使用这些东西:
val st = new SpecificThing("hi")
val fn1: (Thing[String]) => String = (t: Thing[String]) => { t.thingA }
println(doSomething(fn1, st))
这会打印 hi
。到目前为止,一切都很好。但是我比较懒,不喜欢打那么多,所以我把程序改成下面这样:
type MyThing = Thing[String]
val st = new SpecificThing("hi")
val fn2: (MyThing) => String = (t: MyThing) => { t.thingA }
println(doSomething(fn2, st))
这也打印 hi
。极好!编译器可以分辨出 SpecificThing
既是 Thing[String]
又是 MyThing
。但是这个案例呢?
val st = new SpecificThing("hi")
val fn3: (SpecificThing) => String = (t: SpecificThing) => { t.thingA }
println(doSomething(fn3, st))
现在我得到:
Error:(14, 23) type mismatch;
found : SpecificThing => String
required: Thing[?] => ?
println(doSomething(fn3, st))
^
这是怎么回事?什么是 Thing[?]
?
f3
不是 Thing[String] => String
,而是 SpecificThing => String
。例如,为什么它们不兼容:
class SpecificThing2 extends Thing[String] {
def thingB = 2.0
}
val f4: SpecificThing2 => String = {
st: SpecificThing2 => f"%f${st.thingB / 3.0}"
}
val t = new Thing[String]("haha"){}
f4(t) // would be an error when f4 tried to access t.thingB
更正式地说,Function1
在其第一个类型参数 Function1[-T, +R]
.
一个Thing[?]
就是这个样子;它是某种未知类型 X
的 Thing[X]
。编译器正在大胆地尝试推断类型 A
应该是什么,但它无法使其工作:它需要一个 Thing[A] => A
用于某些(未知的)类型 A
,并且您将其传递给 SpecificThing => String
;那是错误。