You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何证明Scala匹配类型可解析为特定具体类型?

Scala匹配类型(Match Type)的类型证明问题

我正尝试实现一个使用match type的trait,该匹配类型的右侧类型预先已知,但无法让编译器接受我的类型证明。这对我来说比较陌生,若问题浅显还请见谅。能否有人帮我理解如何实现需求?

最小复现代码

class NumberBox {}

class LongBox {}

trait Boxer[T] {
  def box(): Boxer.Box[T]
}

object Boxer {
  type Box[T] = T match
    case Long => LongBox
    case _ => NumberBox
}

case class Val[T](v: T) extends Boxer[T] {
  def box(): Boxer.Box[T] = v match
    case _: Long => new LongBox()
    case _ => new NumberBox()
}

// 此处我们试图证明Boxer.Box[T]是NumberBox
case class NoLongs[T](v: Boxer[T])(using Boxer.Box[T] =:= NumberBox) extends Boxer[T] {
  override def box(): Boxer.Box[T] = new NumberBox()
}

NoLongs(Val(1))

编译错误信息

Found:    NumberBox
Required: Boxer.Box[T]

Note: a match type could not be fully reduced:

  trying to reduce  Boxer.Box[T]
  failed since selector  T
  does not match  case Long => LongBox
  and cannot be shown to be disjoint from it either.
  Therefore, reduction cannot advance to the remaining case

    case _ => NumberBox
    override def box(): Boxer.Box[T] = new NumberBox()

解决方案

问题出在编译器无法自动利用Boxer.Box[T] =:= NumberBox这个类型等式证据完成类型转换,必须显式调用该证据来实现转换:

修改NoLongs类的实现:

case class NoLongs[T](v: Boxer[T])(using ev: Boxer.Box[T] =:= NumberBox) extends Boxer[T] {
  override def box(): Boxer.Box[T] = ev(new NumberBox())
}

原理说明

=:=本质是一个函数式的类型证据,它的apply方法可以将右侧类型的实例转换为左侧类型的实例。虽然编译器知道Boxer.Box[T]和NumberBox等价,但不会自动执行转换,必须显式调用这个证据来让编译器确认类型兼容性。

当调用NoLongs(Val(1))时,编译器会推导出T为Int,此时Boxer.Box[Int]会被归约为NumberBox,对应的类型等式证据会被自动合成,无需手动传入。

内容的提问来源于stack exchange,提问作者fehrvuerh93

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 20:03:10