实现数字
我对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).foo
和foo
这样的东西只是为了复杂而定义的, 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
通过指定,应该考虑从T
到G
隐式转换,您允许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