Skip to content

Correlating match types with pattern matching expressions #6709

Closed
@johnynek

Description

@johnynek

I've been trying to use match types to implement a type-level binary nat type.

Here is the code I would ideally like to work:

object Main {

  enum BinNat {
    case Zero
    // 2n + 1
    case Odd[N <: BinNat](n: N)
    // 2(n + 1)
    case Even[N <: BinNat](n: N)
  }

  import BinNat._

  type Inc[N <: BinNat] <: BinNat =
    N match {
      case Zero.type => Odd[Zero.type]
      case Odd[n] => Even[n]
      case Even[n] => Odd[Inc[n]]
    }

  def inc(b: BinNat): Inc[b.type] =
    b match {
      case Zero => Odd(Zero)
      case Odd(n) => Even(n)
      case Even(n) =>
        // 2(n + 1) + 1 = 2(inc(n)) + 1
        Odd(inc(n))
    }
}

The error message I get is:

[error] -- [E007] Type Mismatch Error: /Users/oscar/oss/dotty_tests/src/main/scala/Main.scala:30:22                                                                                     
[error] 30 |      case Zero => Odd(Zero)
[error]    |                   ^^^^^^^^^
[error]    |                   Found:    Main.BinNat
[error]    |                   Required: Main.Inc[Main.BinNat(b)]
[error] -- [E007] Type Mismatch Error: /Users/oscar/oss/dotty_tests/src/main/scala/Main.scala:31:25                                                                                     
[error] 31 |      case Odd(n) => Even(n)
[error]    |                     ^^^^^^^
[error]    |                     Found:    Main.BinNat
[error]    |                     Required: Main.Inc[Main.BinNat(b)]
[error] -- [E007] Type Mismatch Error: /Users/oscar/oss/dotty_tests/src/main/scala/Main.scala:34:11                                                                                     
[error] 34 |        Odd(inc(n))
[error]    |        ^^^^^^^^^^^
[error]    |        Found:    Main.BinNat
[error]    |        Required: Main.Inc[Main.BinNat(b)]
[error] three errors found

I have tried several different variants (using manual sealed trait/case classes, matching on _: Zero.type, explicitly adding type annotations in the def inc method... each seemed to trigger different errors and I couldn't find any that worked.

expectation

I'd like it to compile, or suggest a better action to take in the error message

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions