Performance numbers

I am new to Scala. I want to write several mathematical objects (Complex, Polynomial, etc.) that close during some operations (+, -, *) in such a way that they can be used in generics and implicit casts can be used.

I think I decided the first bit.

trait GroupUnderAddition[T] { def + (t : T) : T } case class Real(d : Double) extends GroupUnderAddition[Real] { def + (r : Real) = Real(d + rd) } 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(rd, 0) def test[G <: GroupUnderAddition[G]](a : G, b : G) = a + b def main(args : Array[String]) { println(test(Real(5), Real(2))) } } 

Now, how can I write test () to

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

returns Complex (7, 1)?

+7
source share
3 answers

The basic idea is that all GroupUnderAdditions are incompatible, since it seems to you that you want to work with complex algebra, I would suggest creating a superclass, including GoupUnderAddition. However, it is not recommended to make it a case class (see Warnings if you have a case class extending the 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))) } } 
+2
source

The problem is that implicit def not considered for converting arguments unless you specify a method definition for this.

Therefore, if you have something like Real(5).foo and foo are only defined for complex, an implicit def will work for that.

If you have one such method: def foo(c : Complex) = ... , you can not call it foo(Real(5)) .

If you want to apply an implicit conversion, you must specify your method so that its arguments can be converted. For the above foo method, you can do it like this:

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

Then you can call foo(Real(5)) , and the transform will be used.

Adapted to your specific problem, you can write a test method as follows:

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

By indicating that implicit conversions from T to G should be taken into account, you allow the test method to take test(Real(5), Complex(2,1)) .

However, for now this will not work. So you still cannot call it with test(Complex(2,1), Real(5)) , because there is no implicit conversion of the second argument.

An easy way to account for both transformations would be to write this as follows:

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

Unfortunately, the compiler somehow outputs Any for G when calling this method, as described above. I don’t know right now how to solve this problem, and I sent this answer in the hope that someone else could fill in this last piece of the puzzle.

Given the final definition above, you can at least call the method anyway when specifying the full types:

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

The real problem is that you are making the (incorrect) assumption that test(Real(5), Complex(2, 1)) is clearly defined in some way, given what you wrote. Consider the following:

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

This fits your definition of "GroupUnderAddition" perfectly, but there is no point trying to add Word ("Hello") to Real (2). What is the result?

What you are trying to encode is a specific addition operator in a larger domain β€” it appears to be a region of polynomials over C β€” and indicates that some subgroups of this object are closed relative to the addition operator. The ChrisJamesC approach can happily be extended to a polynomial ring that will capture what you want.

+1
source

All Articles