1

我很好奇是否可以移植我的无类型项目以使用 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 具有 type "tag" | "attrs" | "children",而模式匹配情况应该将其减少为“标记” .

如何实现我请求的行为?

4

1 回答 1

2

正确的是

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. 匹配表达式模式没有警卫
  2. 匹配表达式 scrutinee's type 是匹配类型 scrutinee's type 的子类型
  3. 匹配表达式和匹配类型的 case 数相同
  4. 匹配表达式模式都是 Typed Patterns,这些类型是=:=匹配类型中对应的类型模式

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

于 2020-10-20T00:22:05.117 回答