Generics 实施数字

Generics 实施数字,generics,scala,Generics,Scala,我对Scala还是个新手。我想写几个数学对象(复数、多项式等),它们在一些运算(+、-、*)下是闭合的,这样它们可以用于泛型,也可以使用隐式转换 我似乎已经解决了第一个问题 trait GroupUnderAddition[T] { def + (t : T) : T } case class Real(d : Double) extends GroupUnderAddition[Real] { def + (r : Real) = Real(d + r.d) } case clas

我对Scala还是个新手。我想写几个数学对象(复数、多项式等),它们在一些运算(+、-、*)下是闭合的,这样它们可以用于泛型,也可以使用隐式转换

我似乎已经解决了第一个问题

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

返回复数(7,1)?

主要思想是所有GroupUnderAddition都不兼容,因此您似乎想要使用复数代数,我建议构建一个包含GoupUnderAddition的超类。但是,不建议将其设置为案例类(如果您有扩展
案例类的
案例类
,请参阅警告)


问题是参数转换不考虑
隐式def
,除非指定方法定义

因此,如果您有类似于
Real(5).foo
的内容,并且
foo
仅为复杂定义,那么
隐式def
将适用于此

如果您有这样一个方法:
def foo(c:Complex)=……
,那么您可以不使用
foo(Real(5))
来调用它

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

def foo[T](c : T)(implicit ct : T => Complex) = ...`
def test[G <: GroupUnderAddition[G],T](a : T, b : G)(implicit ag: T => G) = a + b
def test[G <: GroupUnderAddition[G],T1, T2](a : T1, b : T2)(implicit ag: T1 => G, bg: T2 => G) = a + b
然后可以调用
foo(Real(5))
并使用转换

根据您的具体问题,您可以编写如下测试方法:

def foo[T](c : T)(implicit ct : T => Complex) = ...`
def test[G <: GroupUnderAddition[G],T](a : T, b : G)(implicit ag: T => G) = a + b
def test[G <: GroupUnderAddition[G],T1, T2](a : T1, b : T2)(implicit ag: T1 => G, bg: T2 => G) = a + b
不幸的是,当调用上述方法时,编译器不知何故为
G
派生了
Any
。我现在不知道该如何解决这个问题,我发布了这个答案,希望其他人能填补这个谜题的最后一部分

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

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

这里真正的问题是,根据您所写的内容,您正在(错误地)假设
测试(real(5),Complex(2,1))
在任何方面都是定义良好的。考虑以下事项:

case class Word(s : String) extends GroupUnderAddition[Word] {
  def +(w : Word) = Word(s + w.s)
}
这完全满足了您对“GroupUnderAddition”的定义,但尝试在一个真实的(2)中添加一个单词(“Hello”)是没有意义的。结果如何


您试图编码的是一个更大域内的特定加法运算符-它似乎是C上多项式的域-并指定该域的某些子群在加法运算符下闭合。ChrisJamesC的方法可以很高兴地扩展到多项式环,它将捕获您想要的东西。

我当然可以这样做,但我想保留泛型。按照你的方式做,如果我想用两个多项式调用test,我需要重写整个过程。是的,但是你有两个不同的问题,第一个问题是你想创建generic
GroupUnderAddition
,它将实现方法
+
。另一方面,您希望在加法下有一个特定的
实现两种不同类型的数字:
实数
复数
。这就是为什么你要考虑隐式def,但在你的例子中,我没有找到一个解决方案。考虑到我有一个隐式实数=>复杂函数,test(Real(5),Complex(2,1))定义得很好。我不想让这件事发生在两个孩子身上。