Scala中如何自动生成类型类的交换律实例?
Scala 3类型类交换律自动实例生成问题
我正在探索Scala的类型系统,受Scala 3的Multiversal Equality启发,遇到一个有趣的挑战:定义了表示交换操作的类型类CommutativeAdd,希望当存在(T1, T2)的实例时,自动生成(T2, T1)的实例,避免重复编写代码。
简化代码示例
package typst.tpredef trait CommutativeAdd[-T1 <: TAny, -T2 <: TAny, +Out <: TAny]: def add(t1: T1, t2: T2): Out object CommutativeAdd: def apply[T1 <: TAny, T2 <: TAny, Out <: TAny](using instance: CommutativeAdd[T1, T2, Out], ): CommutativeAdd[T1, T2, Out] = instance given canAddTNoneTAny[T <: TAny]: CommutativeAdd[TNone, T, T] with { def add(t1: TNone, t2: T): T = t2 } given canAddTAnyTNone[T <: TAny]: CommutativeAdd[T, TNone, T] with { def add(t1: T, t2: TNone): T = t1 } extension [T1 <: TAny, T2 <: TAny, Out <: TAny]( t1: T1 )(using canAdd: CommutativeAdd[T1, T2, Out]) @targetName("add") inline infix def +(t2: T2): Out = canAdd.add(t1, t2) val a = TInteger(1) + tNone val b = tNone + TInteger(1) // <- 此处报错
错误信息
value + is not a member of typst.tpredef.TNone. An extension method was tried, but could not be fully constructed: typst.tpredef.+[typst.tpredef.TNone, T2, Out](typst.tpredef.tNone)( /* ambiguous: both given instance canAddTNoneTAny in package typst.tpredef and given instance canAddAnyTNone in package typst.tpredef match type typst.tpredef.CommutativeAdd[typst.tpredef.TNone, T2, Out] */ summon[typst.tpredef.CommutativeAdd[typst.tpredef.TNone, T2, Out]] ) failed with: Ambiguous given instances: both given instance canAddTNoneTAny in package typst.tpredef and given instance canAddAnyTNone in package typst.tpredef match type typst.tpredef.CommutativeAdd[typst.tpredef.TNone, T2, Out] of parameter canAdd of method + in package typst.tpredef
已尝试的解决方案
- 手动交换参数:手动定义参数交换后的given实例,可行但存在代码重复,不够优雅。
- 使用Swap方法:在
CommutativeAdd对象中添加swap方法转换实例,但仍需手动创建对应的given实例。 - 使用元组:用元组表示add方法参数,虽能定义对应实例,但无法实现真正的类型级交换律。
- 使用联合类型:尝试用联合类型表示参数,但联合类型本身不具备类型级交换性,无法自动生成交换后的实例。
补充细节
程序中包含TAny、TNone、tNone、TInteger等类型:TNone类似Unit,tNone类似(),TInteger是装箱Int,TAny是TNone、TInteger等类型的联合类型。希望通过CommutativeAdd类型类实现这些类型间加法的交换性,例如TInteger(1) + tNone与tNone + TInteger(1)等价。
这仅用于学习探索,欢迎提供创意性解决方案,希望得到Scala下的可行思路。
内容的提问来源于stack exchange,提问作者Julian A Avar C
相关产品推荐
相关产品推荐

