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

如何约束Scala方法类型参数仅接受具体类型,拒绝抽象类型参数

如何约束类型参数仅接受具体类型(拒绝抽象类型参数)?

以下代码编译无警告,但运行结果不符合预期:

inline def isXAssignableToY[X <: Matchable, Y]: Boolean = {
    inline erasedValue[X] match {
        case _: Y => true
        case _ => false
    }
}

def isSerializable[A <: Matchable]: Boolean = isXAssignableToY[A, Serializable]

def isSuperOfString[B]: Boolean = isXAssignableToY[String, B]

@main def test19058(): Unit = {
    val a = isXAssignableToY[String, Serializable]
    println(a) // 按预期输出true

    val b = isSerializable[String]
    println(b) // 输出false,不符合预期

    val c = isSuperOfString[Serializable]
    println(c) // 输出false,不符合预期
}

isSerializable和isSuperOfString未达到预期效果,原因是它们向isXAssignableToY传入了抽象类型参数。

现在需要约束isXAssignableToY的用法,使得当传入抽象类型参数时编译器直接报错。已知为方法添加inline修饰符可以解决问题,但这不是想要的方案。


尝试方案1:通过ClassTag检测

尝试通过两个无操作的summonInline调用ClassTag来实现:

inline def isXAssignableToY[X <: Matchable, Y]: Boolean = {
    summonInline[ClassTag[X]]
    summonInline[ClassTag[Y]]
    inline erasedValue[X] match {
        case _: Y => true
        case _ => false
    }
}

这个方案有一定改进:可以检测传入X和Y的直接抽象类型参数,但并非完整解决方案——它无法检测嵌套在类型构造器中的抽象类型参数。


尝试方案2:递归类型类IsSpecific

为解决嵌套场景,尝试使用递归生成隐式实例的类型类:

trait IsSpecific[T]

object IsSpecific {
    inline given [F[_], A](using fs: IsSpecific[A], ct: ClassTag[F[A]]): IsSpecific[F[A]] = new IsSpecific[F[A]] {}

    inline given [T](using ct: ClassTag[T]): IsSpecific[T] = new IsSpecific[T] {}

    // 需要为不同元数的类型构造器添加更多case
}

inline def isXAssignableToY[X <: Matchable, Y](using xs: IsSpecific[X], ys: IsSpecific[Y]): Boolean = {
    inline erasedValue[X] match {
        case _: Y => true
        case _ => false
    }
}

但该方案存在两个问题:

  1. 需要让第一个given的优先级高于第二个,目前不知道如何实现;
  2. 即便优先级问题解决,处理所有元数的类型构造器会非常繁琐。

相关问题

当涉及内联展开产生的类型模式匹配时,会出现误导性的不可达警告?


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 16:27:35