【问题标题】:scala's spire framework : I am unable to operate on a groupscala的尖顶框架:我无法对组进行操作
【发布时间】:2013-10-08 21:00:25
【问题描述】:

我尝试使用数学框架 spire,但出现错误消息:

import spire.algebra._
import spire.implicits._

trait AbGroup[A] extends Group[A]

final class Rationnel_Quadratique(val n1: Int = 2)(val coef: (Int, Int)) {
  override def toString = {
    coef match {
        case (c, i) =>
            s"$c + $i√$n"
    }
  }

  def a() = coef._1

  def b() = coef._2

  def n() = n1


} 

object Rationnel_Quadratique {

  def apply(coef: (Int, Int),n: Int = 2)= {
    new Rationnel_Quadratique(n)(coef)
  }

}

object AbGroup {

  implicit object RQAbGroup extends AbGroup[Rationnel_Quadratique] {

    def +(a: Rationnel_Quadratique, b: Rationnel_Quadratique): Rationnel_Quadratique = Rationnel_Quadratique(coef=(a.a() + b.a(), a.b() + b.b()))

    def inverse(a: Rationnel_Quadratique): Rationnel_Quadratique = Rationnel_Quadratique((-a.a(), -a.b()))

    def id: Rationnel_Quadratique = Rationnel_Quadratique((0, 0))
  }

} 


object euler66_2 extends App {

  val c = Rationnel_Quadratique((1, 2))
  val d = Rationnel_Quadratique((3, 4))
  val e = c + d
  println(e)

}

程序预计会添加1+2√2和3+4√2,但我却出现了这个错误:

找不到 spire.algebra.AdditiveSemigroup[Rationnel_Quadratique] 类型的证据参数的隐含值 val e = c + d ^

我认为我错过了一些重要的东西(隐式的使用?)

【问题讨论】:

  • object euler66_2 方法中尝试import AbGroup._
  • 你好,它不会改变任何东西
  • 在这种情况下,尝试将 RQAbGroup 设为 AbGroup[Rationnel_Quadratique] 类型的 val。
  • 我试过这个:val groupe=AbGroup.RQAbGroup val c = Rationnel_Quadratique((1, 2)) val d = Rationnel_Quadratique((3, 4)) val e = c + d,我确定问题来自于 Rationnel_Quadratique 值没有链接到一个组。但我不是很擅长隐式,我会尝试获取一些关于这个的教程。

标签: scala math spire


【解决方案1】:

您似乎没有正确使用 Spire。

Spire 已经有一个AbGroup 类型,所以你应该使用它而不是重新定义你自己的。这是一个使用我创建的名为X 的简单类型的示例。

import spire.implicits._
import spire.algebra._

case class X(n: BigInt)

object X {
  implicit object XAbGroup extends AbGroup[X] {
    def id: X = X(BigInt(0))
    def op(lhs: X, rhs: X): X = X(lhs.n + rhs.n)
    def inverse(lhs: X): X = X(-lhs.n)
  }
}

def test(a: X, b: X): X = a |+| b

请注意,对于组(以及半群和幺半群),您将使用 |+| 而不是 +。要获得加分,您需要使用AdditiveSemigroup 定义一些东西(例如Semiring、或Ring、或Field 或其他东西)。

如果有意义的话,您还将使用.inverse|-|,而不是一元和二元-

查看您的代码,我也不确定您的实际数字类型是否正确。如果我想为n 添加两个具有不同值的数字会怎样?

无论如何,希望这能让你明白一点。

编辑:由于您似乎也对 Scala 语法感兴趣,所以让我尝试勾画一些可能可行的设计。首先,总有一个更通用的解决方案:

import spire.implicits._
import spire.algebra._
import spire.math._

case class RQ(m: Map[Natural, SafeLong]) {
  override def toString: String = m.map {
    case (k, v) => if (k == 1) s"$v" else s"$v√$k" }.mkString(" + ")
}

object RQ {
  implicit def abgroup[R <: Radical](implicit r: R): AbGroup[RQ] =
    new AbGroup[RQ] {
      def id: RQ = RQ(Map.empty)
      def op(lhs: RQ, rhs: RQ): RQ = RQ(lhs.m + rhs.m)
      def inverse(lhs: RQ): RQ = RQ(-lhs.m)
    }
}

object Test {
  def main(args: Array[String]) {
    implicit val radical = _2
    val x = RQ(Map(Natural(1) -> 1, Natural(2) -> 2))
    val y = RQ(Map(Natural(1) -> 3, Natural(2) -> 4))
    println(x)
    println(y)
    println(x |+| y)
  }
}

这使您可以毫无问题地将不同的根添加在一起,但代价是一些间接性。您还可以通过以下方式更贴近您的设计:

import spire.implicits._
import spire.algebra._

abstract class Radical(val n: Int) { override def toString: String = n.toString }
case object _2 extends Radical(2)
case object _3 extends Radical(3)

case class RQ[R <: Radical](a: Int, b: Int)(implicit r: R) {
  override def toString: String = s"$a + $b√$r"
}

object RQ {
  implicit def abgroup[R <: Radical](implicit r: R): AbGroup[RQ[R]] =
    new AbGroup[RQ[R]] {
      def id: RQ[R] = RQ[R](0, 0)
      def op(lhs: RQ[R], rhs: RQ[R]): RQ[R] = RQ[R](lhs.a + rhs.a, lhs.b + rhs.b)
      def inverse(lhs: RQ[R]): RQ[R] = RQ[R](-lhs.a, -lhs.b)
    }
}

object Test {
  def main(args: Array[String]) {
    implicit val radical = _2
    val x = RQ[_2.type](1, 2)
    val y = RQ[_2.type](3, 4)
    println(x)
    println(y)
    println(x |+| y)
  }
}

这种方法会创建一个假类型来表示您正在使用的任何部首(例如 √2),并在该类型上参数化 QR。这样可以确保没有人会尝试做无效的添加。

希望其中一种方法对您有用。

【讨论】:

  • 谢谢,但我无法调整您的答案;组元素的类型是二次整数 (QI),例如“3+5√2”。它们可以相加,相减,但不能加上'x√2'和'y√3',结果是'x√2+y√3' 不包含在这些组中。我想创建一个组哪些元素是 QI,哪些是泛型:定义:final class Rationnel_Quadratique[n1: Int](val coef: (Int, Int)) 但是当我尝试implicit object RQAbGroup[n:Int] extends AbGroup[Rationnel_Quadratique[Int]] 时出现错误(需要定义或声明)。你知道我该如何解决这个问题吗?
  • (n=3 表示 QI 的类型为 'a+b√3')
  • 所以这看起来像是无效的 Scala 语法。我不认为[n1: Int] 会起作用。如果我是你,我会尝试一个稍微不同的设计,其中激进是隐含的。例如,我们在 spire.math.FixedPoint 中做了类似的事情(有一个隐含的分母)。
  • 当然,我后来看到了,我也试过object RQAbGroup extends AbGroup[Rationnel_Quadratique[Int] {,编译器接受它,但我需要将 Int 参数传递给对象 RQAbGroup。你知道怎么做吗?
  • 我刚刚阅读了您的整个评论,我明天再看看;无论如何,谢谢,很快再见!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-27
  • 1970-01-01
  • 2020-11-30
  • 2018-12-04
  • 2018-06-04
  • 2011-11-09
相关资源
最近更新 更多