如何让匹配类型在 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 项
- The match expression patterns do not have guards
- The match expression scrutinee's type is a subtype of the match type scrutinee's type
- The match expression and the match type have the same number of cases
- 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
我很好奇是否可以将我的非类型化项目移植到 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 项
- The match expression patterns do not have guards
- The match expression scrutinee's type is a subtype of the match type scrutinee's type
- The match expression and the match type have the same number of cases
- 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