简体   繁体   中英

How to get match type to work correctly in Scala 3

I was very curious to see if I could port my untyped project to be typed with Scala 3. Here was my start:

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
    }
  }
}

It does not compile, it throws an error:

> [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]    |   ]

I think it comes from the fact that it does not perceive the pattern matching as a "type filter" for s, since it believes that, in this case, s has the type "tag" | "attrs" | "children" "tag" | "attrs" | "children" "tag" | "attrs" | "children" , whereas the pattern matching case should reduce it to "tag".

How can I implement my requested behavior?

Correct is

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

See item 4 in

  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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM