Is there a way to use the '+' operator as addition on parameters passed to a method as a generic type in Scala? - scala

I recently discovered Scala, and I've written an RK4 solver that I'm trying to generalize as much as possible. After getting it working with arbitrarily large systems, I wanted to get it working with arbitrary numeric data types -but I've run into a wall. When I use a generic data type, no matter what restrictions I place on it, Scala automatically converts everything to strings to use '+'.
Most of what I've tried thus far has ultimately been writing the same thing in different ways. I could explicitly convert everything to the highest precision type I'll be using (BigDecimal) and call it a day, but that misses much of the point of generalizing the function.
This isn't my entire RK4 program, but it is the one piece of code I've been screwing with for the past couple hours:
def vecSum[T : Numeric]( u: Vector[T], v: Vector[T]): Vector[T] = (u, v).zipped.map(_ + _)
It's the vector sum (math vector, the data structure is just coincidental), which takes in two vectors and returns a single vector where each element is the sum of the two corresponding elements in the input vectors.
I'm trying to get it to return a vector of the same numeric type as the inputs, but it only wants to spit out a vector of strings.

Use
def vecSum[T](u: Vector[T], v: Vector[T])(implicit o: Numeric[T]): Vector[T] = (u, v).zipped.map((x, y) => o.plus(x, y))
If you specifically want to use + you can use
import Numeric.Implicits._
def vecSum2[T: Numeric](u: Vector[T], v: Vector[T]): Vector[T] = {
(u, v).zipped.map((x, y) => x + y)
}

Related

Scala equivalent of Java's Number with divide method

I want to generalise this function
def selfSufficiency(a: Seq[Double], b: Seq[Double]): Double =
a.sum/b.sum
I tried using the ideas provided here to implement a more general function that work with Doubles, Floats, Ints, etc.:
def selfSufficiency[A](a: Seq[A], b: Seq[A])
(implicit n: Numeric[A]):A = {
import n._
a.sum/b.sum
}
I however get a remark from eclipse saying that
value / is not a member of type parameter A.
1- How can I implement this in functional/generalisable way?
2- Does my implementation limits the user to have the same type "A" for both inputs? In other words, can I do this with my code?
selfSufficiency(Seq(1,2,3), Seq(2.0,1.3))
if I cannot, please explain how to implement this?
Please note that the code here provide a toy example. In my production function, I add, subtract, find the larger number, etc.
The problem is that Numeric doesn't encode the division function - you need a Fractional.
Thus your code becomes
def selfSufficiency[A](a: Seq[A], b: Seq[A])
(implicit n: Fractional[A]):A = {
import n._
a.sum/b.sum
}
And now it works.
Edit
I just read this part of your question.
Does my implementation limits the user to have the same type "A" for both inputs? In other words, can I do this with my code?
Because both Fractional and Numeric are parametrized in just one T, both arguments have to be from the same type - for example take a look to the div function.
However, since numeric values of less precision are subtypes of the ones with higher (fig 1). You can make it work by upcast, but you will need to help the compiler a little more.
selfSufficiency[Double](Seq(1,2,3), Seq(2.0,1.3)) // res1: Double = 1.8181818181818183
Note: Without specifying the type as Double, the compiler will yield the following error.
error: could not find implicit value for parameter n: Fractional[AnyVal]
fig 1
Reference: https://www.artima.com/pins1ed/scalas-hierarchy.html
What you are looking for is the Fractional trait which is a more narrow Numeric (subtype) that supports div.

Defining function that takes arguments in prefix notation scala

I want to do define a function in scala that takes arguments in prefix notation:
sum i1 i2 i3 ... in
and returns and Int with the sum of all the provided args. Note that I don't want to use parentheses when I call the function.
My goal is to do something like sum i1 plus i2 but I want to start with something simpler first.
NOTE: You might say there is not purpose for doing this if you can use the + operator, but my goal is not to add numbers. I am just using this as a generic learning tool.
Before answering the question, I'd like to point out that scala is first and foremost an object oriented language, so most of the functions you'll want to define will actually be methods on specific objects. I will give answers in more generality for any class T (not necessarily for Int). I also assume that what you want to do on your list of values can be done iteratively, so sum 1 2 3 is actually the same as sum (sum 1 2) 3, so I assume you have some reducer function f: (T, T) => T.
To define an infix operator, so that you can do something like
i1 and i2 and i3 ...
you just have to define a method
and(that: T): T = f(this, that)
on your class T. If you are not able to add methods to your type (eg, if you're using a class from a lib, or Ints), you can use an implicit wrapper for your type:
implicit class ReducibleT(i: T) {
def and(j: T): f(i, j)
}
To define a prefix operator, with infix repeater, such as
sum i1 and i2 and i3 ...
it appears that you cannot do it! That's because an expression like ident1 ident2 ident3 is always (as far as I know) parsed as ident1.ident2(ident3), (unless ident2 ends with a colon, in which case it is reversed). But you cannot define a method for all possible identifiers for your type T (eg, for Ints, you cannot define a method 1 on an object, so sum 1 2 has no meaning whatsoever), so it won't be possible.
However, you can do almost as good:
sum (i1) and i2 and i3 ...
In that case, the parens indicates a function call, so it actually calls the method and on the object sum(i1) (which actually is sum.apply(i1), since all functions are objects with the special method apply). Here is an example:
def sum(i: T) = i
implicit class ReducibleT(i: T) {
def and(j: T): f(i, j)
}
Now, if you understood this second case, it will come to no surprise that you cannot do
sum i1 i2 i3 ...
either. We have to limit ourselves to
sum (i1) (i2) (i3)
using the following:
def sum(i: T) = i
implicit class ReducibleT(i: T) {
def apply(j: T) = f(i, j)
}
Or, to mix things up a bit, you can use implicit conversion to a function:
implicit def tAsReducer(i: T): T => T = f(i, _)

Having hard time to understand why this function is called MapReduce

In my Scala course an example has given. It was about finding a more generalized function, which can be used to define an arithmetic summation function and an arithmetic production function. Here are the functions that should be generalized.
def sum(f:Int=>Int)(a:Int,b:Int):Int ={
if(a>b) 0
else f(a) + sum(f)(a+1,b)
}
def product(f:Int=>Int)(a:Int,b:Int):Int={
if(a>b)1
else f(a)*product(f)(a+1,b)
}
To generalize these functions the teacher gave such a function :
def mapReduce(f:Int=>Int,combine: (Int,Int)=>Int, zero:Int)(a:Int,b:Int):Int ={
if(a>b) zero
else combine(f(a),mapReduce(f, combine, zero)(a+1, b))
}
So mapReduce function can be used to generalize sum and product functions as follows:
def sumGN(f:Int=>Int)(a:Int,b:Int) = mapReduce(f, (x,y)=>(x+y), 0)(a, b)
def productGN(f:Int=>Int)(a:Int,b:Int) = mapReduce(f, (x,y)=>(x*y), 1)(a, b)
I took a look at the definition of map reduce in functional programming but I have a hard time why the generalized function has been named as map reduce above. I can not grasp the relation. Any help will make my very happy.
Regards
Functional programming usually has three central operators: map, reduce (sometimes called fold), and filter.
Map takes a list and an operation and produces a list containing the operation applied to everything in the first list.
Filter takes a list and a test and produces another list containing only the elements that pass the test.
Reduce (or fold) takes a list, an operation, and an initial value and applies the operation to the initial value and the elements in the list, passing the output into itself along with the next list item, producing the operational sum of the list.
If, for example, your list is [2,3,4,5,6,7], your initial value is 1, and your operation is addition, reduction will behave in the following way:
Reduce([2,3,4,5,6,7], +, 1) = ((((((initial + 2) + 3) + 4) + 5) + 6) + 7)
Your instructor may be calling it mapReduce because this is the paradigm's name, though simply reduce would be sufficient as well.
If you're curious as to the significance of his name, you should ask him. He is your instructor and all.
This is by no means an exact explanation (names are fuzzy anyway) but here’s an alternative definition:
def mapReduce(f: Int => Int, combine: (Int, Int) => Int, zero: Int)(a: Int, b: Int): Int ={
if (a > b) zero
else (a to b).map(f).reduce(combine)
}
Do you see the link?
mapReduce's mapping function is f in the question, though there's never an example of its definition. For sum and product it would be the identity function, but if you were summing the squares then the mapping function would be the square function.
mapReduce's reducer function is combine, wherein we are reducing a tuple of accumulator+value to a new accumulator for the next recursion.
I think the missing link besides the code not being very clear is to treat numbers as collections (e.g., 3 is a collection of three 1s). This is quite unusual and I don't know what it buys you but it could be that your teacher will use the analogy between numbers and collections for something more profound later.
Is this from Odersky's coursera course?

How can I write f(g(h(x))) in Scala with fewer parentheses?

Expressions like
ls map (_ + 1) sum
are lovely because they are left-to-right and not nested. But if the functions in question are defined outside the class, it is less pretty.
Following an example I tried
final class DoublePlus(val self: Double) {
def hypot(x: Double) = sqrt(self*self + x*x)
}
implicit def doubleToDoublePlus(x: Double) =
new DoublePlus(x)
which works fine as far as I can tell, other than
A lot of typing for one method
You need to know in advance that you want to use it this way
Is there a trick that will solve those two problems?
You can call andThen on a function object:
(h andThen g andThen f)(x)
You can't call it on methods directly though, so maybe your h needs to become (h _) to transform the method into a partially applied function. The compiler will translate subsequent method names to functions automatically because the andThen method accepts a Function parameter.
You could also use the pipe operator |> to write something like this:
x |> h |> g |> f
Enriching an existing class/interface with an implicit conversion (which is what you did with doubleToDoublePlus) is all about API design when some classes aren't under your control. I don't recommend to do that lightly just to save a few keystrokes or having a few less parenthesis. So if it's important to be able to type val h = d hypot x, then the extra keystrokes should not be a concern. (there may be object allocations concerns but that's different).
The title and your example also don't match:
f(g(h(x))) can be rewritten asf _ compose g _ compose h _ apply x if your concern is about parenthesis or f compose g compose h apply x if f, g, h are function objects rather than def.
But ls map (_ + 1) sum aren't nested calls as you say, so I'm not sure how that relates to the title. And although it's lovely to use, the library/language designers went through a lot of efforts to make it easy to use and under the hood is not simple (much more complex than your hypot example).
def fgh (n: N) = f(g(h(n)))
val m = fgh (n)
Maybe this, observe how a is provided:
def compose[A, B, C](f: B => C, g: A => B): A => C = (a: A) => f(g(a))
basically like the answer above combine the desired functions to a intermediate one which you then can use easily with map.
Starting Scala 2.13, the standard library provides the chaining operation pipe which can be used to convert/pipe a value with a function of interest.
Using multiple pipes we can thus build a pipeline which as mentioned in the title of your question, minimizes the number of parentheses:
import scala.util.chaining._
x pipe h pipe g pipe f

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