scala - 如何在 Scala 中模拟依赖类型

标签 scala types path-dependent-type dependent-type

我正在尝试在 Scala 中定义一个通用的残基类环。残基类环由一些基环(例如整数)和模数(例如二)定义,模数是基环的值。环和它们的元素都是对象,因此模数的类型通常是依赖类型,取决于基环。我知道这在 Scala 中是不允许的(有充分的理由),所以我试图通过近似类型并在构造残留类环时进行运行时检查来模拟它。
ResidueClassRing的定义被无误地接受,但是,Scala 不允许我实例化它,因为参数 two我收到错误消息

type mismatch;
found   : dependenttypetest.DependentTypeTest.two.type 
(with underlying type dependenttypetest.Integers.Integer)  
required: dependenttypetest.EuclideanRing#E

难道我做错了什么?这可能是 Scala 类型检查器中的错误吗?有没有更好的方法来定义 ResidueClassRing ?

这是用于 Helios 的 Eclipse IDE 中的 Scala 2.8.0。 2.7.x 已经出现这个问题。这是代码的简化版本:
package dependenttypetest


class EuclideanRing
{
  thisRing =>

  type E <: EuclideanRingElement;

  def one: E;

  trait EuclideanRingElement 
  {
    def ring = thisRing;

    def +(b: E): E;
    def %(b: E): E;
  }
}


object Integers extends EuclideanRing
{
  type E = Integer;

  val one: Integer = new Integer(1);

  class Integer(n: Int) extends EuclideanRingElement
  {
    val intValue: Int = n;
    def +(b: Integer): Integer = new Integer(intValue + b.intValue);
    def %(b: Integer): Integer = new Integer(intValue % b.intValue);
  }
}


class ResidueClassRing (val baseRing : EuclideanRing, m : EuclideanRing#E) 
{
  val modulus: baseRing.E = 
    m match {
    case e: baseRing.E if m.ring == baseRing => e;
    case _ => throw new IllegalArgumentException("modulus not from base ring");
    };

  type E = ResidueClassRingElement;

  def one: E = new ResidueClassRingElement(baseRing.one);

  class ResidueClassRingElement (e : baseRing.E)
  {
    def representative: baseRing.E = e % modulus;

    def +(b: E) = new ResidueClassRingElement(
      this.representative + b.representative); 
  }
}


object DependentTypeTest extends Application
{
  val two = new Integers.Integer(2);
  val mod2ring = new ResidueClassRing(Integers, two);

  println(mod2ring.one + mod2ring.one);
}

最佳答案

更新:已添加 IntRing澄清 trait Ring 中的变化

问题似乎是类型推断器不会自动选择最具体的类型,而这正是您需要的类型。除此之外,您不能在与定义类型相同的参数列表中拥有依赖类型参数。

您可以做的是在外部作用域中拉取该类型所依赖的实例(在 Rings 类中完成)并强制编译器在实例化 Rings 时选择最具体的类型。类(class):

trait Ring {

  type Element <: EuclideanRingElement

  def one: Element

  // for convenience could be defined anywhere of course
  lazy val rings: Rings[this.type] = new Rings[this.type](this)

  trait EuclideanRingElement {
    def +(e: Element): Element
    def %(e: Element): Element
  }
}

class Rings[R <: Ring](val base: R) {

  class ResidueClassRing(m: base.Element) {

    def one = new Element(base.one)

    class Element(e: base.Element) {
      def repr = e % m
      def +(that: Element) = new Element(this.repr + that.repr)
    }
  }
}

object IntRing extends Ring {

val one = new Element(1)

  class Element(val n: Int) extends EuclideanRingElement {
    def +(that: Element) = new Element(this.n + that.n)
    def %(that: Element) = new Element(this.n % that.n)
    override def toString = n formatted "Int(%d)"
  }
}

现在你可以像这样使用它:
scala> import IntRing._
import IntRing._

scala> val two = new Element(2)
two: IntRing.Element = Int(2)


scala> val r2 = new rings.ResidueClassRing(two)
r2: IntRing.rings.ResidueClassRing = Rings$ResidueClassRing@4b5075f9

关于scala - 如何在 Scala 中模拟依赖类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3932160/

相关文章:

Scala 中的 Java 继承类导致类型不匹配错误

haskell - 通用类型组合的可遍历实例

scala - AKKA 接收消息引用

scala - PlayFramework:如何转换 JSON 数组的每个元素

c - 为什么buf的大小从4变成了1

types - 覆盖 `show` 是一个类型的字段

scala - Scala 中具有隐式封闭实例的路径依赖工厂

scala - 依赖于路径的类型 - 以下代码有什么问题?

scala - “Future.successful(None)”和 “Future(None)”有什么区别