模式匹配中使用的抽象类型的类型不匹配 [英] Type mismatch on abstract type used in pattern matching
问题描述
此代码编译时出现错误:
This code compiles with an error:
def f1[T](e: T): T = e match {
case i:Int => i
case b:Boolean => b
}
// type mismatch;
// found : i.type (with underlying type Int)
// required: T
// case i:Int => i ...
从类型检查的角度来看,实现GADT的这段代码看起来非常相似,但编译时没有错误:
And this code implementing GADT looks pretty identical from type checking perspective, but compiles without error:
sealed trait Expr[T]
case class IntExpr(i: Int) extends Expr[Int]
case class BoolExpr(b: Boolean) extends Expr[Boolean]
def eval[T](e: Expr[T]): T = e match {
case IntExpr(i) => i
case BoolExpr(b) => b
}
在两种情况下,在模式匹配表达式中,我们都知道 i 和 b 是 Int 和 Boolean .为什么在第一个示例中编译失败,而在第二个示例中成功编译?
In both cases inside pattern matching expression we know that i and b are Int and Boolean. Why compilation failed on first example and succeeded on the second one?
推荐答案
第一种情况是不正确的,因为您低估了Scala类型系统中的类型多样性.如果我们在进入case i:Int
分支时知道T
是Int
,或者至少是Int
的超类型,那将是有道理的.但这不是必须的!例如.它可能是 42.type 或
The first case is unsound because you underestimate the variety of types in Scala type system. It would make sense if, when we took case i:Int
branch we knew T
was Int
, or at least a supertype of Int
. But it doesn't have to be! E.g. it could be 42.type or a tagged type.
在第二种情况下没有这样的问题,因为从IntExpr <: Expr[T]
开始,编译器确实知道T
必须完全是Int
.
There's no such problem in the second case, because from IntExpr <: Expr[T]
, the compiler does know T
must be exactly Int
.
这篇关于模式匹配中使用的抽象类型的类型不匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!