[英]Type mismatch on abstract type used in pattern matching
此代碼編譯時出現錯誤:
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 的代碼看起來非常相同,但編譯時沒有錯誤:
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 。 為什么第一個示例編譯失敗而第二個示例編譯成功?
你要求你的函數返回一個類型T
,然后你對Int
和Boolean
模式匹配。 除了您的函數沒有證據表明Int
和Boolean
也是T
類型:當您進行模式匹配時, 您引入了Int <: T
和Boolean <: T
的約束。 您可以將返回類型T
替換為固定類型(如String
並返回一個 String ,或者引入一個同時滿足Int
和Boolean
情況的約束。
//this compiles
def f1[T](e: T ): String = e match {
case _:Int => "integer"
case _:Boolean => "boolean"
}
//this compiles too, but will return AnyVal
def f1[T >: AnyVal](e: T ): T = e match {
case i:Int => i
case b:Boolean => b
}
基本上你不能只是動態地返回任何類型T
因為你需要在編譯時證明你的函數類型檢出。
您示例中的另一個函數通過在案例類IntExpr <: Expr[Int]
和BoolExpr <: Expr[Boolean]
封裝類型約束來避免該問題(注意Expr[_]
在我上面提到的約束中如何等效於T
)。 在編譯時, T 在所有case
都被正確識別(例如,在IntExpr
您知道它是Int
)
除了@Esardes 的回答之外,這還通過為T
定義類型綁定來實現:
scala> def f1[T >: AnyVal](e: T):T = e match {
| case i:Int => i
| case b:Boolean => b
| }
f1: [T >: AnyVal](e: T)T
scala> f1(1)
res3: AnyVal = 1
scala> f1(true)
res4: AnyVal = true
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.