Scala类型表查找

8i9zcol2  于 2023-04-21  发布在  Scala
关注(0)|答案(1)|浏览(135)

给定不透明类型XY,是否可能有一个返回类型Table[X, Y],它解析为XY或第三个类型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] Type Mismatch Error: cmd2.sc:22:77 -----------------------------------
22 |        def +[Y <: ConstrainedInt](m: Y)(using t: AddType[X, Y]): t.Result = n + m
   |                                                                             ^^^^^
   |    Found:    Int
   |    Required: t.Result

更新

试着遵循https://stackoverflow.com/a/76046222的建议。
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] Type Mismatch Error: ---------------------------------------------------------------------
1 |val a: Int = PositiveInt(3) + NegativeInt(-4)
  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |             Found:    constrained.NegativeInt match {
  |               case constrained.PositiveInt => constrained.PositiveInt
  |               case constrained.NegativeInt => Int
  |             }
  |             Required: Int
  |
  | longer explanation available when compiling with `-explain`
1 error found

scala> val a: NegativeInt = NegativeInt(-4) + NegativeInt(-3)
-- [E007] Type Mismatch Error: ---------------------------------------------------------------------
1 |val a: NegativeInt = NegativeInt(-4) + NegativeInt(-3)
  |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |      Found:    TypeTables.AddType[constrained.NegativeInt, constrained.NegativeInt]
  |      Required: constrained.NegativeInt
  |
  |      Note: a match type could not be fully reduced:
  |
  |        trying to reduce  TypeTables.AddType[constrained.NegativeInt, constrained.NegativeInt]
  |        failed since selector  constrained.NegativeInt
  |        does not match  case constrained.PositiveInt => constrained.NegativeInt match {
  |        case constrained.PositiveInt => constrained.PositiveInt
  |        case constrained.NegativeInt => Int
  |      }
  |        and cannot be shown to be disjoint from it either.
  |        Therefore, reduction cannot advance to the remaining case
  |
  |          case constrained.NegativeInt => constrained.NegativeInt match {
  |        case constrained.NegativeInt => constrained.NegativeInt
  |        case constrained.PositiveInt => Int
  |      }
  |
  | longer explanation available when compiling with `-explain`
1 error found
bkhjykvo

bkhjykvo1#

我认为如果你定义AddType作为匹配类型,你可以让你的第一个例子工作,因为你需要覆盖所有的情况。像这样:

type AddType[A <: ConstrainedInt, B <: ConstrainedInt] = A match 
  case PositiveInt => B match 
    case PositiveInt => PositiveInt
    case NegativeInt => ConstrainedInt
    case ConstrainedInt => ConstrainedInt
  case NegativeInt => B match 
    case PositiveInt => ConstrainedInt
    case NegativeInt => NegativeInt
    case ConstrainedInt => ConstrainedInt
  case ConstrainedInt => ConstrainedInt

相关问题