Scala不透明类型:能否用类型表Table[X,Y]实现动态返回类型?
Scala不透明类型的加法类型映射实现问题
问题描述
给定Scala不透明类型X、Y,能否实现返回类型Table[X,Y],使其解析为X、Y或第三种类型Z?
初始尝试:直接类型别名写法
以下代码无法编译:
opaque type ConstrainedInt = Int opaque type PositiveInt <: ConstrainedInt = Int opaque type NegativeInt <: ConstrainedInt = Int object PositiveInt: def apply(n: Int): PositiveInt = require(n > 0) n object NegativeInt: def apply(n: Int): NegativeInt = require(n < 0) n type AddType[PositiveInt, PositiveInt] = PositiveInt type AddType[NegativeInt, NegativeInt] = NegativeInt extension[X <: ConstrainedInt](x: X) def +[Y <: ConstrainedInt](y: Y): AddType[X, Y] = x + y
初始尝试:类型类写法
类型类版本同样无法编译:
trait AddType[X <: ConstrainedInt, Y <: ConstrainedInt]: type Result <: ConstrainedInt given AddType[PositiveInt, PositiveInt] = new AddType { type Type = PositiveInt } given AddType[NegativeInt, NegativeInt] = new AddType { type Type = NegativeInt } extension[X <: ConstrainedInt](x: X) def +[Y <: ConstrainedInt](y: Y)(using t: AddType[X, Y]): t.Result = x + y
报错信息
[E007] 类型不匹配错误: cmd2.sc:22:77 ----------------------------------- 22 | def +[Y <: ConstrainedInt](m: Y)(using t: AddType[X, Y]): t.Result = n + m | ^^^^^ | 找到: Int | 需要: t.Result
更新尝试
参考相关思路后,编写了以下代码:
constrained.scala
object constrained: opaque type PositiveInt = Int opaque type NegativeInt = Int object PositiveInt: def apply(n: Int): PositiveInt = require(n > 0) n object NegativeInt: def apply(n: Int): NegativeInt = require(n < 0) n extension[X <: PositiveInt | NegativeInt](x: X) def +[Y <: PositiveInt | NegativeInt](y: Y): TypeTables.AddType[X, Y] = x + y
TypeTables.scala
object TypeTables: import constrained.* type AddType[X <: PositiveInt | NegativeInt, Y <: PositiveInt | NegativeInt] = X match case PositiveInt => Y match case PositiveInt => PositiveInt case NegativeInt => Int case NegativeInt => Y match case NegativeInt => NegativeInt case PositiveInt => Int
编译及测试命令
scalac constrained.scala TypeTables.scala scala -classpath .
测试结果及报错
scala> import constrained.* scala> import TypeTables.* scala> PositiveInt(3) + NegativeInt(-4) val res0: constrained.NegativeInt match { case constrained.PositiveInt => constrained.PositiveInt case constrained.NegativeInt => Int } = -1 scala> NegativeInt(-4) + PositiveInt(3) val res1: TypeTables.AddType[constrained.NegativeInt, constrained.PositiveInt] = -1 scala> NegativeInt(-3) + NegativeInt(-4) | val res2: TypeTables.AddType[constrained.NegativeInt, constrained.NegativeInt] = -7 scala> val a: Int = PositiveInt(3) + NegativeInt(-4) -- [E007] 类型不匹配错误: --------------------------------------------------------------------- 1 |val a: Int = PositiveInt(3) + NegativeInt(-4) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | 找到: constrained.NegativeInt match { | case constrained.PositiveInt => constrained.PositiveInt | case constrained.NegativeInt => Int | } | 需要: Int | | 编译时加上 `-explain` 可查看详细解释 1 error found scala> val a: NegativeInt = NegativeInt(-4) + NegativeInt(-3) -- [E007] 类型不匹配错误: --------------------------------------------------------------------- 1 |val a: NegativeInt = NegativeInt(-4) + NegativeInt(-3) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | 找到: TypeTables.AddType[constrained.NegativeInt, constrained.NegativeInt] | 需要: constrained.NegativeInt | | 注意:匹配类型无法完全化简: | | 尝试化简 TypeTables.AddType[constrained.NegativeInt, constrained.NegativeInt] | 失败,因为选择器 constrained.NegativeInt | 不匹配 case constrained.PositiveInt => constrained.NegativeInt match { | case constrained.PositiveInt => constrained.PositiveInt | case constrained.NegativeInt => Int | } | 且无法证明两者互斥。 | 因此,化简无法推进到剩余的case: | | case constrained.NegativeInt => constrained.NegativeInt match { | case constrained.NegativeInt => constrained.NegativeInt | case constrained.PositiveInt => Int | } | | 编译时加上 `-explain` 可查看详细解释 1 error found
内容的提问来源于Stack Exchange,提问作者Nil Admirari
相关产品推荐
相关产品推荐

