【发布时间】:2015-07-19 19:55:12
【问题描述】:
我在 Scala 中偶然发现了一些让我非常困惑的东西。似乎高阶函数的参数类型不是多态的。下面是我的意思的演示:
class A
class B extends A
def call(f: A => A):A = f(new A)
def A2A(a: A): A = new A
def A2B(a: A): B = new B
def B2A(b: B): A = new A
def B2B(b: B): B = new B
call(A2A) // Works
call(A2B) // Works
call(B2A) // Error!
call(B2B) // Error!
两次调用的错误信息相同:
<console>:12: error: type mismatch;
found : B => A
required: A => A
call(new B, B2A)
<console>:12: error: type mismatch;
found : B => B
required: A => A
call(new B, B2B)
A2A 和 A2B 工作,所以不是返回类型导致问题,它必须是参数类型。这与类型擦除有关吗?
我认为我正在尝试做的事情在逻辑上没有任何问题(也许有?)所以我怀疑这是类型系统的怪癖?
编辑
感谢您的回答!事实证明,这毕竟是我的错误逻辑。问题在于call 的定义。它需要一个将A(或子类型)作为参数的函数。
B2A 和 B2B 都采用 B(或子类型),因此与 call 的定义不兼容。
我通过引入 A 扩展自称为 ALike 的特征解决了这个问题,并更改了 call 的定义,以便它接受任何具有 ALike 作为超类型的参数。
trait ALike
class A extends ALike
class B extends A
def call[T <: ALike](t: T, f: T => A): A = f(t)
def A2A(a: A): A = a
def A2B(a: A): B = new B
def B2A(b: B): A = new A
def B2B(b: B): B = b
call(new A, A2A)
call(new A, A2B)
call(new B, B2A)
call(new B, B2B)
【问题讨论】:
-
我认为您在编辑中输入了
B2A的结果类型。应该是def B2A(b: B): A = new A
标签: scala functional-programming