Scala Implicit Conversion Function Name Clashes - scala

I am working with a simple complex number case class in Scala and would like to create an add function that works between complex numbers, doubles and ints. Below is a simple example of a working solution:
case class Complex(re: Double, im: Double)
implicit def toComplex[A](n: A)(implicit f: A => Double): Complex = Complex(n, 0)
implicit class NumberWithAdd[A](n: A)(implicit f: A => Complex) {
def add(m: Complex) = Complex(n.re + m.re, n.im + m.im)
}
Note I am deliberately not including the add function in the complex case class. Using the above I can do all of this:
scala> val z = Complex(1, 2); val w = Complex(2, 3)
z: Complex = Complex(1.0,2.0)
w: Complex = Complex(2.0,3.0)
scala> z add w
res5: Complex = Complex(3.0,5.0)
scala> z add 1
res6: Complex = Complex(2.0,2.0)
scala> 1 add z
res7: Complex = Complex(2.0,2.0)
I'd like to use '+' instead of 'add, but however this does not work. I get the following error:
Error:(14, 4) value + is not a member of A$A288.this.Complex
z + 1
^
Both z + w and 1 + z still work however.
What I'd like to know is why does changing the function name from 'add' to '+' break this? Is there an alternate route to getting this functionality (without simply putting the add function in the complex case class)? Any help would be appreciated.
Edit - Motivation
I'm playing around with monoids and other algebraic structures. I would like to be able to generalise the '...WithAdd' function to automatically work for any class that has a corresponding monoid:
trait Monoid[A] {
val identity: A
def op(x: A, y: A): A
}
implicit class withOp[A](n: A)(implicit val monoid: Monoid[A]) {
def +(m: A): A = monoid.op(n, m)
}
case class Complex(re: Double, im: Double) {
override def toString: String = re + " + " + im + "i"
}
class ComplexMonoid extends Monoid[Complex] {
val identity = Complex(0, 0)
def op(z: Complex, w: Complex): Complex = {
Complex(z.re + w.re, z.im + w.im)
}
}
implicit val complexMonoid = new ComplexMonoid
Using the above I can now do Complex(1, 2) + Complex(3, 1) giving Complex = 4.0 + 3.0i. This is great for code reuse as I could now add extra functions to the Monoid and withAdd function (such as appling op n times to an element, giving the power function for multiplication) and it would work for any case class that has a corresponding monoid. It is only with complex numbers and trying to incorporate doubles, ints, etc., that I then run into the problem above.

I would use a regular class, not a case class. Then it would be easy to create methods to add or subtract these Complex numbers, like:
class Complex(val real : Double, val imag : Double) {
def +(that: Complex) =
new Complex(this.real + that.real, this.imag + that.imag)
def -(that: Complex) =
new Complex(this.real - that.real, this.imag - that.imag)
override def toString = real + " + " + imag + "i"
}
As the source page shows, it will now support something that looks like operator overloading (it's not, because + and - are functions and not operators).
The problem with implicit class NumberWithAdd and its method + is that the same method also exist in number classes such as Int and Double. The + method of NumberWithAdd basically allows you to start with a number that can be casted to Complex and add a Complex object to that first item. That is, the left hand value can be anything (as long as it can be converted) and the right hand value must be Complex.
That works great for w + z (no need to convert w) and 1 + z (implicit conversion for Int to Complex is available). It fails for z + 1 because + is not available in the class Complex .
Since z + 1 is actually z.+(1), Scala will look for other possible matches for +(i: Int) in classes that Complex can be converted into. It also checks NumberWithAdd, which does have a + function but that one required a Complex as right hand value. (It would match a function that requires an Int as right hand value.) There are other functions named + that do accept Int, but there's no conversion from Complex to what those functions want as left hand values.
The same definition of + does work when it's in the (case) class Complex. In that case, both w + z and z + 1 simply use that definition. The case 1 + z is now a little more complicated. Since Int does not have a function + that accepts a Complex value, Scala will find the one that does (in Complex) and determines whether or not it is possible to convert Int into Complex. That is possible using the implicit functions, the conversion takes place and the function is executed.
When the function + in the class NumberWithAdd is renamed add, there's no confusion with functions in Int because Int does not have a function +. So Scala will try harder to apply the function add and it will do the Int to Complex conversion. It will even do that conversion when you try 1 add 2.
Note: My explanations may not fully describe the actual inner workings.

Related

value - is not a member of type parameter T | Scala Error

I am using Scala 2.13.
I wrote the following code representing a 2D Point which works on only scala.math.Numeric types:
class Point[T: Numeric](val x: T, val y: T) {
def getDistance(otherPoint: Point[T]): Double = {
math.sqrt(math.pow(otherPoint.x - x, 2) + math.pow(otherPoint.y - y, 2))
}
override def toString = "(" + x + "," + y + ")"
}
in the 4th line, I get the error "value - is not a member of type parameter T", click to see the location where error occurs:
click to see error location
Where am I going wrong here? (I am new to generics, type bounds in scala)
Problem 1:
To use mathematical operators given a Numeric bound, you need to
import Numeric.Implicits._
(and Fractional/Integral.Implicits._ to get division operations). Without it you need to do something like
Numeric[T].minus(otherPoint.x, x)
or to give a name to the implicit Numeric parameter instead of using a context bound. With the import you can just write
otherPoint.x - x
The import can be declared at any scope: usually at the top of the file, but it can go inside the method if you only need it once.
Problem 2:
math.pow works only on Double, and there's no equivalent function for all Numerics in the standard library. So convert to Double using toDouble method (you could define a generic squaring function, but not really square root).
First, you need an extra import to enable the convenient symbol ops on a Numeric.
After that, feed pow() a parameter type that it understands.
class Point[T: Numeric](val x: T, val y: T) {
import Numeric.Implicits._
def getDistance(otherPoint: Point[T]): Double = {
math.sqrt(math.pow((otherPoint.x - x).toDouble, 2) +
math.pow((otherPoint.y - y).toDouble, 2))
}
override def toString = "(" + x + "," + y + ")"
}

Set of WrappedArray: Type arguments [Int] do not conform to method empty's type parameter bounds [T <: AnyRef]

I'm trying to make a function that calculates how many combinations of elements with repetition there are given an array of values and a exact sum value.
But I'm getting an error:
Error:(23, 38) type arguments [Int] do not conform to method empty's type parameter bounds [T <: AnyRef]
r(maxValue,WrappedArray.empty[Int],Set[WrappedArray[Int]]()).size
It seems there is a type problem in the empty set I'm trying to pass to the function.
I choosed WrappedArrays following this [question]: Scala: lightweight way to put Arrays in a Set or Map in order to be able to have a set of arrays without duplicates.
import scala.collection.mutable.WrappedArray
def Combinations(maxValue: Int): Int = {
val values= Array(1,2,5,10)
def r (a:Int,can:WrappedArray[Int],sol:Set[WrappedArray[Int]]): Set[WrappedArray[Int]] ={
values.map(x=> if (a-x > 0) r(a-x,can:+x,sol) else if (a-x == 0) sol + (can:+x).sorted else sol).reduce((x, y)=>x union y)
}
r(maxValue,WrappedArray.empty[Int],Set[WrappedArray[Int]]()).size
}
Combinations(4)
Thanks
WrappedArray.empy is bounded by AnyRef, as Int inherits from AnyVal you cannot declare your wrappedArray this way.
However you can declare your empty array this way new WrappedArray.ofInt(Array())
Here is a little fiddle for you
https://scalafiddle.io/sf/PioRREd/0
I've never seen anyone ever importing WrappedArray for anything. It's a rather obscure implementation detail for providing collection methods on ordinary arrays, it has no place in the solution of combinatoric problems. Another general remark: methodNames are written in camel-case, starting with a lowercase letter.
Here is a more idiomatic (and also much simpler) solution:
def numCombinations(
sum: Int,
coins: List[Int] = List(1, 2, 5, 10)
): Long = {
coins match {
case Nil => if (sum == 0) 1L else 0L
case h :: t => {
(0 to sum / h)
.map { i => numCombinations(sum - i * h, t) }
.sum
}
}
}
println(numCombinations(4))
Example: for n = 4, it will find the combinations
1 + 1 + 1 + 1
1 + 1 + 2
2 + 2
and output 3.

Create a Scala function without explicitly declaring the types

I'd like to create a simple function:
def sum(a,b) = a + b
But then it won't compile, I have to do
def sum(a:Int, b:Int) : Int = a + b
Which is much longer to code and type-bound. Is it possible to do it without specifying the type, just as I'd do in OCaml:
let sum x y = x + y
In Scala, you can omit a function's return type, but not the argument types:
def sum(a:Int, b:Int) = a + b // return type inferred to be Int
For more about Scala type inference, see: http://docs.scala-lang.org/tutorials/tour/local-type-inference.html

scala currying by nested functions or by multiple parameter lists

In Scala, I can define a function with two parameter lists.
def myAdd(x :Int)(y :Int) = x + y
This makes it easy to define a partially applied function.
val plusFive = myAdd(5) _
But, I can accomplish something similar by defining and returning a nested function.
def myOtherAdd(x :Int) = {
def f(y :Int) = x + y
f _
}
Cosmetically, I've moved the underscore, but this still feels like currying.
val otherPlusFive = myOtherAdd(5)
What criteria should I use to prefer one approach over the other?
There are at least four ways to accomplish the same thing:
def myAddA(x: Int, y: Int) = x + y
val plusFiveA: Int => Int = myAddA(5,_)
def myAddB(x: Int)(y : Int) = x + y
val plusFiveB = myAddB(5) _
def myAddC(x: Int) = (y: Int) => x + y
val plusFiveC = myAddC(5)
def myAddD(x: Int) = {
def innerD(y: Int) = x + y
innerD _
}
val plusFiveD = myAddD(5)
You might want to know which is most efficient or which is the best style (for some non-performance based measure of best).
As far as efficiency goes, it turns out that all four are essentially equivalent. The first two cases actually emit exactly the same bytecode; the JVM doesn't know anything about multiple parameter lists, so once the compiler figures it out (you need to help it with a type annotation on the case A), it's all the same under the hood. The third case is also extremely close, but since it promises up front to return a function and specifies it on the spot, it can avoid one internal field. The fourth case is pretty much the same as the first two in terms of work done; it just does the conversion to Function1 inside the method instead of outside.
In terms of style, I suggest that B and C are the best ways to go, depending on what you're doing. If your primary use case is to create a function, not to call in-place with both parameter lists, then use C, because it tells you what it's going to do. (This version is also particularly familiar to people coming from Haskell, for instance.) On the other hand, if you are mostly going to call it in place but will only occasionally curry it, then use B. Again, it says more clearly what it's expected to do.
You could also do this:
def yetAnotherAdd(x: Int) = x + (_: Int)
You should choose the API based on intention. The main reason in Scala to have multiple parameter lists is to help type inference. For instance:
def f[A](x: A)(f: A => A) = ...
f(5)(_ + 5)
One can also use it to have multiple varargs, but I have never seen code like that. And, of course, there's the need for the implicit parameter list, but that's pretty much another matter.
Now, there are many ways you can have functions returning functions, which is pretty much what currying does. You should use them if the API should be thought of as a function which returns a function.
I think it is difficult to get any more precise than this.
Another benefit of having a method return a function directly (instead of using partial application) is that it leads to much cleaner code when using infix notation, allowing you to avoid a bucketload of parentheses and underscores in more complex expressions.
Consider:
val list = List(1,2,3,4)
def add1(a: Int)(b: Int) = a + b
list map { add1(5) _ }
//versus
def add2(a: Int) = a + (_: Int)
list map add2(5)

How does one write the Pythagoras Theorem in Scala?

The square of the hypotenuse of a right triangle is equal to the sum of the squares on the other two sides.
This is Pythagoras's Theorem. A function to calculate the hypotenuse based on the length "a" and "b" of it's sides would return sqrt(a * a + b * b).
The question is, how would you define such a function in Scala in such a way that it could be used with any type implementing the appropriate methods?
For context, imagine a whole library of math theorems you want to use with Int, Double, Int-Rational, Double-Rational, BigInt or BigInt-Rational types depending on what you are doing, and the speed, precision, accuracy and range requirements.
This only works on Scala 2.8, but it does work:
scala> def pythagoras[T](a: T, b: T, sqrt: T => T)(implicit n: Numeric[T]) = {
| import n.mkNumericOps
| sqrt(a*a + b*b)
| }
pythagoras: [T](a: T,b: T,sqrt: (T) => T)(implicit n: Numeric[T])T
scala> def intSqrt(n: Int) = Math.sqrt(n).toInt
intSqrt: (n: Int)Int
scala> pythagoras(3,4, intSqrt)
res0: Int = 5
More generally speaking, the trait Numeric is effectively a reference on how to solve this type of problem. See also Ordering.
The most obvious way:
type Num = {
def +(a: Num): Num
def *(a: Num): Num
}
def pyth[A <: Num](a: A, b: A)(sqrt: A=>A) = sqrt(a * a + b * b)
// usage
pyth(3, 4)(Math.sqrt)
This is horrible for many reasons. First, we have the problem of the recursive type, Num. This is only allowed if you compile this code with the -Xrecursive option set to some integer value (5 is probably more than sufficient for numbers). Second, the type Num is structural, which means that any usage of the members it defines will be compiled into corresponding reflective invocations. Putting it mildly, this version of pyth is obscenely inefficient, running on the order of several hundred thousand times slower than a conventional implementation. There's no way around the structural type though if you want to define pyth for any type which defines +, * and for which there exists a sqrt function.
Finally, we come to the most fundamental issue: it's over-complicated. Why bother implementing the function in this way? Practically speaking, the only types it will ever need to apply to are real Scala numbers. Thus, it's easiest just to do the following:
def pyth(a: Double, b: Double) = Math.sqrt(a * a + b * b)
All problems solved! This function is usable on values of type Double, Int, Float, even odd ones like Short thanks to the marvels of implicit conversion. While it is true that this function is technically less flexible than our structurally-typed version, it is vastly more efficient and eminently more readable. We may have lost the ability to calculate the Pythagrean theorem for unforeseen types defining + and *, but I don't think you're going to miss that ability.
Some thoughts on Daniel's answer:
I've experimented to generalize Numeric to Real, which would be more appropriate for this function to provide the sqrt function. This would result in:
def pythagoras[T](a: T, b: T)(implicit n: Real[T]) = {
import n.mkNumericOps
(a*a + b*b).sqrt
}
It is tricky, but possible, to use literal numbers in such generic functions.
def pythagoras[T](a: T, b: T)(sqrt: (T => T))(implicit n: Numeric[T]) = {
import n.mkNumericOps
implicit val fromInt = n.fromInt _
//1 * sqrt(a*a + b*b) Not Possible!
sqrt(a*a + b*b) * 1 // Possible
}
Type inference works better if the sqrt is passed in a second parameter list.
Parameters a and b would be passed as Objects, but #specialized could fix this. Unfortuantely there will still be some overhead in the math operations.
You can almost do without the import of mkNumericOps. I got frustratringly close!
There is a method in java.lang.Math:
public static double hypot (double x, double y)
for which the javadocs asserts:
Returns sqrt(x2 +y2) without intermediate overflow or underflow.
looking into src.zip, Math.hypot uses StrictMath, which is a native Method:
public static native double hypot(double x, double y);