加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

具有Lambda表达式的复杂Scala类型推断

发布时间:2020-12-16 10:02:02 所属栏目:安全 来源:网络整理
导读:我正在为一个我在 Scala中构建的实验库工作的DSL,我遇到了Scala类型推断的一些棘手的特性,因为它与lambda表达式参数有关,这些参数似乎没有在 Programming In Scala中讨论过. . 在我的库中,我有一个特性,Effect [-T],用于表示可以应用于类型T的对象的临时修饰
我正在为一个我在 Scala中构建的实验库工作的DSL,我遇到了Scala类型推断的一些棘手的特性,因为它与lambda表达式参数有关,这些参数似乎没有在 Programming In Scala中讨论过. .

在我的库中,我有一个特性,Effect [-T],用于表示可以应用于类型T的对象的临时修饰符.我有一个对象myEffects,它有一个名为=的方法接受一个参数效果类型[PlayerCharacter].最后,我有一个泛型方法,当[T]时,用于通过接受条件表达式和另一个效果作为参数来构造条件效果.签名如下:

def when[T](condition : T => Boolean) (effect : Effect[T]) : Effect[T]

当我使用上述签名调用“when”方法时,将其结果传递给=方法,它无法推断lambda表达式的参数类型.

myEffects += when(_.hpLow()) (applyModifierEffect) //<-- Compiler error

如果我将“when”的参数组合到一个参数列表中,Scala能够很好地推断lambda表达式的类型.

def when[T](condition : T => Boolean,effect : Effect[T]) : Effect[T]

/* Snip */

myEffects += when(_.hpLow(),applyModifierEffect) //This works fine!

如果我完全删除第二个参数,它也可以工作.

def when[T](condition : T => Boolean) : Effect[T]

/* Snip */

myEffects += when(_.hpLow()) //This works too!

但是,出于美观原因,我真的希望将参数作为单独的参数列表传递给“when”方法.

我在Programming in Scala第16.10节中的理解是,编译器首先查看方法类型是否已知,如果是,则使用它来推断它的参数的预期类型.在这种情况下,最外层的方法调用是=,它接受Effect [PlayerCharacter]类型的参数.由于when [T]的返回类型是Effect [T],并且传递结果的方法需要Effect [PlayerCharacter]类型的参数,它可以推断T是PlayerCharacter,因此lambda的类型表达式作为第一个参数传递给“when”是PlayerCharacter =>布尔.这似乎是在一个参数列表中提供参数时它是如何工作的,那么为什么将参数分成两个参数列表呢?

解决方法

我自己对Scala比较陌生,而且我没有很多关于类型推理如何工作的详细技术知识.所以最好带上一粒盐.

我认为不同之处在于编译器无法证明两个Ts的条件相同:T =>布尔和效果:效果[T],在双参数列表版本中.

我相信当你有多个参数列表时(因为Scala将其视为定义一个返回消耗下一个参数列表的函数的方法),编译器会一次处理一个参数列表,而不是像单个参数列表版本一样.

所以在这种情况下:

def when[T](condition : T => Boolean,applyModifierEffect) //This works fine!

applyModifierEffect的类型和myEffects =的必需参数类型可以帮助约束_.hpLow()的参数类型;所有的Ts必须是PlayerCharacter.但在以下内容中:

myEffects += when(_.hpLow()) (applyModifierEffect)

编译器必须独立地计算出when(_.hpLow())的类型,以便它可以检查将它应用于applyModifierEffect是否有效.并且就其自身而言,_.hpLow()没有为编译器提供足够的信息来推断这是[PlayerCharacter](_.hpLow())的时候,所以它不知道返回类型是函数type Effect [PlayerCharacter] =>效果[PlayerCharacter],因此它不知道在该上下文中应用该函数是有效的.我的猜测是类型推断只是没有连接点,并发现只有一种类型可以避免类型错误.

至于其他有效的案例:

def when[T](condition : T => Boolean) : Effect[T]

/* Snip */

myEffects += when(_.hpLow()) //This works too!

这里返回类型的when和它的参数类型更直接连接,而不经过参数类型和currying创建的额外函数的返回类型.由于myEffects =需要Effect [PlayerCharacter],因此T必须是具有hpLow方法的PlayerCharacter,并且编译器已完成.

希望有更多知识渊博的人可以纠正我的细节,或者指出我是否完全咆哮了错误的树!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读