Scala 3.3中使用扩展方法时出现类型不匹配错误
Scala扩展方法类型不匹配问题排查与修复
问题描述
以下Scala代码编译时出现类型不匹配等错误:
enum Tree[+A]: case Leaf(value: A) case Branch(left: Tree[A], right: Tree[A]) extension (t: Tree[Int]) def firstPositive: Int = t match case Leaf(i) => i case Branch(l, r) => val lpos = l.firstPositive if lpos > 0 then lpos else r.firstPositive
报错信息:
-- [E008] Not Found Error: ----------------------------------------------------- 137 | if lpos > 0 then lpos else r.firstPositive | ^^^^^^ |value > is not a member of Tree[Int] => Int, but could be made available as an extension method. | |One of the following imports might make progress towards fixing the problem: | | import math.Ordered.orderingToOrdered | import math.Ordering.Implicits.infixOrderingOps | -- [E007] Type Mismatch Error: ------------------------------------------------- 137 | if lpos > 0 then lpos else r.firstPositive | ^^^^ | Found: (lpos : Tree[Int] => Int) | Required: Int | | longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: ------------------------------------------------- 137 | if lpos > 0 then lpos else r.firstPositive | ^^^^^^^^^^^^^^^ | Found: Tree[Int] => Int | Required: Int | | longer explanation available when compiling with `-explain` 3 errors found
实际调用l.firstPositive时,其类型为Tree[Int] => Int而非预期的Int,虽可通过l.firstPositive(l)强制调用,但失去了扩展方法的语法优势。该代码片段来自《Functional Programming in Scala Second Edition》第52页。
错误原因
把extension定义在Tree枚举内部时,编译器会将其解析为针对Tree类型的扩展方法工厂,而非直接绑定到Tree[Int]实例的方法。此时调用l.firstPositive,拿到的是扩展方法的函数对象,而非执行该方法后的Int结果。
修复方案
将extension块移到Tree枚举的外部(顶级作用域或合适的其他作用域),让编译器正确识别为针对Tree[Int]实例的扩展方法:
enum Tree[+A]: case Leaf(value: A) case Branch(left: Tree[A], right: Tree[A]) // 扩展方法移至枚举外部 extension (t: Tree[Int]) def firstPositive: Int = t match case Leaf(i) => i case Branch(l, r) => val lpos = l.firstPositive if lpos > 0 then lpos else r.firstPositive
说明
移到外部后,Tree[Int]的实例(如Branch的l和r)可以直接调用firstPositive,返回值类型为预期的Int,所有类型错误都会消失。若需要将扩展方法与Tree关联,也可将其放在Tree的伴生对象中,效果一致。
内容的提问来源于stack exchange,提问作者Wiktor
相关产品推荐
相关产品推荐

