如何约束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 } }
但该方案存在两个问题:
- 需要让第一个
given的优先级高于第二个,目前不知道如何实现; - 即便优先级问题解决,处理所有元数的类型构造器会非常繁琐。
相关问题
当涉及内联展开产生的类型模式匹配时,会出现误导性的不可达警告?
内容的提问来源于stack exchange,提问作者Readren
相关产品推荐
相关产品推荐

