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"
, whereas the pattern matching case should reduce it to "tag".
How can I implement my requested behavior?
Correct is
https://scastie.scala-lang.org/DmytroMitin/sHIgdt5wR7mKZyJm6vEXJA/1
See item 4 in
http://dotty.epfl.ch/docs/reference/new-types/match-types.html