首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Scala:高阶函数参数类型的多态性

Scala:高阶函数参数类型的多态性
EN

Stack Overflow用户
提问于 2015-07-19 10:03:58
回答 2查看 437关注 0票数 1

我在Scala中偶然发现了一些让我感到困惑的东西。似乎高阶函数的参数类型不是多态的。下面是我的意思:

代码语言:javascript
复制
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!

对于两个调用,错误消息都是相同的:

代码语言:javascript
复制
<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 (或子类型)作为参数的函数。

B2AB2B都采用B (或子类型),因此与call的定义不兼容。

我通过引入AALike扩展而来的特性来解决这个问题,并修改了call的定义,以便它接受任何以ALike作为超级类型的参数。

代码语言:javascript
复制
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)
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-07-19 10:15:36

调用(F)是期望一个函数可以接受一个A(或任何子类型)并返回一个A(或任何子类型)。原因1和2工作是因为您的函数定义可以接受A或A的任何子类型,而在1中,返回A(满足A的条件)或在2中返回B(满足A的子类型的条件)。

后两者不能工作的原因是,您传入一个只能接受B并返回A或B的函数,为了了解为什么这是一个问题,假设您有类C扩展。B2A将无法处理C,这意味着,根据定义,调用(F)将无法处理输入C,尽管它是A的一个子类型。这是一个编译错误,原因是调用的定义。

票数 3
EN

Stack Overflow用户

发布于 2015-07-19 10:24:26

Scala Function的参数是相反的。在A => A的情况下,这意味着您可以创建一个接受超级A类型的函数,但是不能创建一个接受像B这样的子类型的函数。

您可以定义一个接受Any的函数

代码语言:javascript
复制
def Any2A(any: Any) = new A 
def Any2B(any: Any) = new B

call(Any2A) // A = A@b5bddc9
call(Any2B) // A = B@62c1c65f

函数1-T1,+R

Function1的参数是逆变的,结果是协变的,这意味着在A => A类型的函数中

  • B是结果类型(协变量):A2B时,可以返回A
  • B是参数的类型(B2AB2B)时,不能接受A,但是可以传递超级A类型,如Any (Any2AAny2B)。

关于Function的反方差(和协方差)的一些解释可以在http://www.artima.com/pins1ed/type-parameterization.html#19.6中找到。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31500053

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档