如何让匹配类型在 Scala 3 中正常工作

How to get match type to work correctly in Scala 3

我很好奇是否可以将我的非类型化项目移植到 Scala 3 中。 这是我的开始:

object Main {
  type HtmlNodeRecord[X]= X match {
    case "tag" => String
    case "attrs" => List[(String, String)]
    case "children" => List[HtmlNode]
  }
  case class HtmlNode(tag: String, attrs: List[(String, String)], children: List[HtmlNode]) {
    def apply(s: "tag" | "attrs" | "children"):  HtmlNodeRecord[s.type] = s match {
      case "tag" => tag
      case "attrs" => attrs
      case "children" => children
    }
  }
}

编译失败,报错:

> [E007] Type Mismatch Error: Main.scala:10:22
> [error] 10 |      case "tag" => tag
> [error]    |                    ^^^
> [error]    |   Found:    (HtmlNode.this.tag : String)
> [error]    |   Required: Main.HtmlNodeRecord[
> [error]    |     (s : ("tag" : String) | ("attrs" : String) | ("children" : String))
> [error]    |   ]

我认为这是因为它没有将模式匹配视为 s 的“类型过滤器”,因为它认为,在这种情况下,s 具有类型 "tag" | "attrs" | "children",而模式匹配案例应将其简化为“标签”。

如何实现我请求的行为?

正确的是

type HtmlNodeRecord[X] = X match {
  case "tag" => String
  case "attrs" => List[(String, String)]
  case "children" => List[HtmlNode]
}
case class HtmlNode(tag: String, attrs: List[(String, String)], children: List[HtmlNode]) {
  def apply(s: "tag" | "attrs" | "children"): HtmlNodeRecord[s.type] = s match {
    case _: "tag" => tag
    case _: "attrs" => attrs
    case _: "children" => children
  }
}

https://scastie.scala-lang.org/DmytroMitin/sHIgdt5wR7mKZyJm6vEXJA/1

参见

中的第 4 项
  1. The match expression patterns do not have guards
  2. The match expression scrutinee's type is a subtype of the match type scrutinee's type
  3. The match expression and the match type have the same number of cases
  4. The match expression patterns are all Typed Patterns, and these types are =:= to their corresponding type patterns in the match type

http://dotty.epfl.ch/docs/reference/new-types/match-types.html