模式匹配中使用的抽象类型的类型不匹配 [英] Type mismatch on abstract type used in pattern matching

查看:76
本文介绍了模式匹配中使用的抽象类型的类型不匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此代码编译时出现错误:

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分支时知道TInt,或者至少是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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆