实现数字

我对Scala很陌生。 我想写几个在某些操作(+, - ,*)下关闭的数学对象(Complex,Polynomial等),以便可以在泛型中使用它们,并且可以使用隐式转换。

我似乎解决了第一点。

trait GroupUnderAddition[T] {
  def + (t : T) : T
}

case class Real(d : Double) extends GroupUnderAddition[Real] {
  def + (r : Real) = Real(d + r.d)
}

case class Complex(re : Double, im : Double) extends GroupUnderAddition[Complex] {
  def + (c : Complex) = Complex(re + c.re, im + c.im)
}

object Test {
  implicit def real_to_complex(r : Real) = Complex(r.d, 0)

  def test[G <: GroupUnderAddition[G]](a : G, b : G) = a + b

  def main(args : Array[String]) {
    println(test(Real(5), Real(2)))
  }
}

现在,我该如何编写test()

test(Real(5), Complex(2, 1))

返回复杂(7,1)?


主要思想是所有GroupUnderAddition都不兼容,所以你似乎想要使用复杂的代数,我建议构建一个包括GoupUnderAddition的超类。 但是不建议使它成为一个案例类(见警告,如果你有一个case class延伸的case class

trait GroupUnderAddition[T] {
  def + (t : T) : T
}

class ComplexAlgebra(_re:Double, _im:Double) extends(GroupUnderAddition[ComplexAlgebra]) {
  val re = _re
  val im = _im     
  def + (c : ComplexAlgebra) = new ComplexAlgebra(re + c.re, im + c.im)  
}

case class Real(d : Double) extends ComplexAlgebra(d, 0)

case class Complex(real : Double, imaginary : Double) extends ComplexAlgebra(real,imaginary)

object Test {

  def test(a : ComplexAlgebra, b : ComplexAlgebra) = a + b

  def main(args : Array[String]) {
    println(test(Real(5), Real(2)))
  }
}

问题是implicit def不考虑参数转换,除非你指定方法定义来这样做。

因此,如果你有像Real(5).foofoo这样的东西只是为了复杂而定义的, implicit def将适用implicit def

如果你有这样一个方法: def foo(c : Complex) = ...你可能不会用foo(Real(5))调用它。

如果要应用隐式转换,则必须指定方法以使其参数可以转换。 对于上面的foo方法,你可以这样做:

def foo[T](c : T)(implicit ct : T => Complex) = ...`

然后调用foo(Real(5))并转换将被使用。

根据您的具体问题,您可以编写像这样的测试方法:

def test[G <: GroupUnderAddition[G],T](a : T, b : G)(implicit ag: T => G) = a + b

通过指定,应该考虑从TG隐式转换,您允许test方法现在接受test(Real(5), Complex(2,1))

但是,它现在还不能运行。 所以你还不能用test(Complex(2,1), Real(5))调用它,因为没有第二个参数的隐式转换。

解释这两种转换的简单方法是将其写成如下形式:

def test[G <: GroupUnderAddition[G],T1, T2](a : T1, b : T2)(implicit ag: T1 => G, bg: T2 => G) = a + b

不幸的是,当调用上面的方法时,编译器以某种方式派生Any for G 我现在不知道如何解决这个问题,并且我发布了这个答案,希望别人能够填补这个难题。

鉴于上述最终定义,您至少可以在指定完整类型时以任何方式调用该方法:

println(test[Complex,Real,Complex](Real(5), Complex(2, 1)))
println(test[Complex,Complex,Real](Complex(2,1), Real(5)))

这里真正的问题在于,假设test(Real(5), Complex(2, 1))以任何方式定义良好(假设你写了什么test(Real(5), Complex(2, 1))那么你做出(不正确的)假设。 考虑以下:

case class Word(s : String) extends GroupUnderAddition[Word] {
  def +(w : Word) = Word(s + w.s)
}

这完全符合您对GroupUnderAddition的定义,但尝试向Real(2)添加Word(“Hello”)是没有意义的。 结果是什么?

你想要编码的是一个更大的域内的特定加法运算符 - 它似乎是C上多项式的域 - 并且指定在加法运算符下它的某些子组被封闭。 ChrisJamesC的方法可以很好地扩展到多项式环,它可以捕捉你想要的东西。

链接地址: http://www.djcxy.com/p/57563.html

上一篇: Implementing numbers

下一篇: how to control pc mouse from android device without client server