Scala 3 中的类型否定

问题描述 投票:0回答:1

是否可以在 Scala 3 中实现防故障

Not[A]
类型? 这是几年前提出的一个问题:我如何在 scala 中拥有否定类型。 不幸的是,如果其中任何一个是抽象类型,基于“未给出
A <:< B
”的解决方案就会失败:缺乏证据不是缺乏证据的谬误。从技术上讲, 使用宏,应该可以验证表达式的类型并在不知道完整类型信息时产生错误。但是,我希望它不仅在“不是
A <:< B
”时也能工作,而且只有在
A with B
有效
Nothing
时才有效:任何一种类型都是密封/最终的,不能混入另一种。另一方面,在那种情况下,不应该需要有关这两种类型的完整信息:如果 A 是最终的,则 B 的任何上限既不是类型变量也不是
A
应该有效。

动机:

sealed trait Marker
sealed trait A[X]
final class Special[X <: Marker] extends A[X]
final class Generic[X :Not[Marker]#Proof] extends A[X]

在上面的例子中,如果我有一个

a :A[Marker]
,那么我肯定知道
a.asInstanceOf[Special[Marker]]
是正确的。

scala reflection implicit scala-3
1个回答
1
投票

类型类

Not
不能用 Scala 3 隐式定义。歧义把戏不再奏效了。隐式解析的语义发生了变化。不传播歧义错误。

Scala 2 implicits 和 Scala 3 given/using 之间的区别 (answer)

这就是为什么在 Scala 3 中内置

Not
的原因:
scala.util.NotGiven

https://docs.scala-lang.org/scala3/reference/contextual/givens.html#negated-givens

https://docs.scala-lang.org/scala3/reference/changed-features/implicit-resolution.html

并非所有具有类型类的语言

Not
都是可能的。例如在 Haskell 中这是不可能的(使用标准工具)

如何有条件地声明一个实例?答案

如何实现`Constraint`反射? [基于可用约束的 Ad-Hoc 多态性]

根据类型参数的类型类采取行动?

无法以无标记最终方式/使用类型类和实例对我的组件进行编码

你可以尝试类似的东西

import scala.util.NotGiven
import scala.compiletime.summonFrom

final class Generic[X](using (NotGiven[X <:< Marker] || IsAbstract[X])) extends A[X]

trait ||[A, B]
object ||:
  transparent inline given [A, B]: (A || B) =
    summonFrom {
      case _: A => new (A || B) {}
      case _: B => new (A || B) {}
    }
import scala.quoted.*

trait IsAbstract[X]
object IsAbstract:
  transparent inline given [X]: IsAbstract[X] = ${mkIsAbstractImpl[X]}

  def mkIsAbstractImpl[X: Type](using Quotes): Expr[IsAbstract[X]] =
    import quotes.reflect.*
    val tpe = TypeRepr.of[X]

    if tpe.typeSymbol.isAbstractType
    then '{new IsAbstract[X] {}}
    else report.errorAndAbort(s"${tpe.show} is not abstract")

普通的union类型

NotGiven[X <:< Marker] | IsAbstract[X]
不优先类型类的实例,因此导致歧义。

如有必要,您可以添加

IsSealed
IsFinal

© www.soinside.com 2019 - 2024. All rights reserved.