加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

如何在Scala中模拟依赖类型

发布时间:2020-12-16 08:53:38 所属栏目:安全 来源:网络整理
导读:我正在尝试在 Scala中定义一个通用的残留类环.残基类环由一些基环(例如整数)和模数(例如两个)定义,该模数是来自基环的值.环和它们的元素都是对象,因此模数的类型通常是依赖类型,这取决于基环.我理解这在Scala中是不允许的(有充分的理由),所以我试图通过近似
我正在尝试在 Scala中定义一个通用的残留类环.残基类环由一些基环(例如整数)和模数(例如两个)定义,该模数是来自基环的值.环和它们的元素都是对象,因此模数的类型通常是依赖类型,这取决于基环.我理解这在Scala中是不允许的(有充分的理由),所以我试图通过近似类型并在构造残差类环时进行运行时检查来模拟它.

ResidueClassRing的定义被接受而没有错误,但是,Scala不允许我实例化它,因为参数二我得到了错误消息

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);
}

解决方法

这似乎有效,但在计算代表时我无法摆脱演员:

package dependenttypetest

abstract class EuclideanRing{
  thisRing =>
  type E <: EuclideanRingElement;
  def one: E;
  trait EuclideanRingElement
  {
    def ring = thisRing;

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

class 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);
    override def toString = "Int" + intValue
  }
}

object Integers extends Integers 

class ResidueClassRing[ER <: EuclideanRing] (modulus : ER#E) {
  val baseRing = modulus.ring
  type E = ResidueClassRingElement;
  def one: E = new ResidueClassRingElement(baseRing.one);

  class ResidueClassRingElement (e : baseRing.E)
  {
    def representative = e % modulus.asInstanceOf[baseRing.E];
    def +(b: E) = new ResidueClassRingElement(
      this.representative + b.representative);
    override def toString = "RC(" + representative + ")"
  }
}

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

  println(mod2ring.one + mod2ring.one)
}

顺便说一句:小心应用程序特征,它被合理地弃用了.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读