将新的 Scala 类型类语法与 GADT 类型相结合

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

我正在用 Scala 编写一个库,并决定使用 3.5.0 版本中引入的更新(实验)语法来处理类型类。所以我的代码有:

trait HasBoundary:
  type Self
  extension (self : Self)
    def boundary[Coefficient : Fractional] : Chain[Self, Coefficient]

trait HasDimension:
  type Self
  extension (self : Self)
    def dim : Int

trait OrderedCell extends HasBoundary with HasDimension

class Chain[Cell : OrderedCell, Coefficient : Fractional](val entries : Map[Cell, Coefficient])

sealed trait ElementaryInterval:
  def n : Int

case class DegenerateInterval(n : Int) extends ElementaryInterval

case class FullInterval(n : Int) extends ElementaryInterval

此时,我发现自己正在努力编写

given
语句以使整个 GADT
ElementaryInterval = DegenerateInterval | FullInterval
成为
OrderedCell
类型类的成员。

我可以写:

given DegenerateInterval is OrderedCell:
  extension (t : DegenerateInterval)
    def boundary[CoefficientT : Fractional] = Chain(Map.empty)
    def dim : Int = 0
  end extension
end given

given FullInterval is OrderedCell:
  extension (t : DegenerateInterval)
    def boundary[CoefficientT : Fractional as fr] = Chain(Map.from(DegenerateInterval(t.n+1) → fr.one, DegenerateInterval(t.n) → fr.negate(fr.one)))
    def dim : Int = 1
  end extension
end given

但是我的

boundary
函数没有给出正确的返回类型 - 它们似乎需要坚持各自的案例类,并且无法爬上继承层次结构。

或者我可以将其全部写为

ElementaryInterval
类型,如

given ElementaryInterval is OrderedCell:
  extension (t : ElementaryInterval)
    def boundary[Coefficient : Fractional as fr] = t match {
      case DegenerateInterval(_) => Chain(Map.empty)
      case FullInterval(n) => Chain(Map.from(DegenerateInterval(n+1) → fr.one, DegenerateInterval(n) → fr.negate(fr.one)))
  end extension
end given

但是,在构建包含

Chain
DegenerateInterval
FullInterval
对象时,我似乎遇到了问题,因为它会为案例类寻找
given
子句,而不是我为密封编写的子句。特质。


所以,总结一下我的问题/问题:

我可以将类型类的新语法与 GADT 的

sealed trait
/
case class
模式结合起来吗?如何编写
given
子句来实现类型类成员资格,以便它与 GADT 中的继承结构兼容?

是否有某种方法可以以某种合理的方式注释

given
实例中的方差?

scala typeclass scala-3 gadt type-members
1个回答
0
投票

我仍然想更好地理解 GADT 构造和类型类之间的相互作用,但我已经成功解决了这个特殊的结:

关键似乎是比预期更多的地方显式类型注释。以下似乎有效:

given ElementaryInterval is OrderedCell:
  extension (t : ElementaryInterval)
    def boundary[Coefficient : Fractional as fr] = t match {
      case DegenerateInterval(_) => Chain[ElementaryInterval, Coefficient](Map.empty)
      case FullInterval(n) => Chain[ElementaryInterval, Coefficient](Map.from(DegenerateInterval(n+1) → fr.one, DegenerateInterval(n) → fr.negate(fr.one)))
    def dim : Int = t match {
      case DegenerateInterval(_) => 0
      case FullInterval(_) => 1
    }

换句话说,如果我不允许类型推断落在

Chain[DegenerateInterval, Coefficient]
之类的东西上,它会在检查
Chain
上的条件时正确解析给定的实例。

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