You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 07:52:56