How to make a generic numeric method in scala 3? - scala

I've seen this question answered before, but for scala 2 using implicit. However, scala 3 lacks the implicit keyword, which leaves me at square one.
So, how would I go about making a generic method like this toy example:
def add2[T](number: T) = number + 2
that is, how do I write a method that works equally well for Double, Float, Int, and so on?

As new in Scala 3 doc mentions - implicits (and their syntax) have been heavily revised and now you can achieve this with using clause:
def add2[T](number: T)(using num: Numeric[T]): T = {
import num._
number + num.fromInt(2)
}

Related

Type Classe implementation best syntax

When implementing Typeclasses for our types, we can use different syntaxes (an implicit val or an implicit object, for example). As an example:
A Typeclass definition:
trait Increment[A] {
def increment(value: A): A
}
And, as far as I know, we could implement it for Int in the two following ways:
implicit val fooInstance: Increment[Int] = new Increment[Int] {
override def increment(value: Int): Int = value + 1
}
// or
implicit object fooInstance extends Increment[Int] {
override def increment(value: Int): Int = value + 1
}
I always use the first one as for Scala 2.13 it has an abbreviation syntax that looks like this:
implicit val fooInstance: Increment[Int] = (value: Int) => value + 1
But, is there any real difference between them? or is there any recommendation or standard to do this?
There is a related question about implicit defs and implicit classes for conversions, but I'm going more to the point of how to create (best practices) instances of Typeclasses, not about implicit conversions
As far as I know the differences would be:
objects have different initialization rules - quite often they will be lazily initialized (it doesn't matter if you don't perform side effects in constructor)
it would also be seen differently from Java (but again, you probably won't notice that difference in Scala)
object X will have a type X.type which is a subtype of whatever X extends or implements (but implicit resolution would find that it extends your typeclass, though perhaps with a bit more effort)
So, I wouldn't seen any difference in the actual usage, BUT the implicit val version could generate less JVM garbage (I say garbage as you wouldn't use any of that extra compiler's effort in this particular case).

What are the different types of functions you can create based on the position of the function call?

def atMost(actual: Int, limit: Int): Int = max(actual, limit)
Say I have a function like above atMost, I have to call it like:
atMost(100, 25) // returns 25
What if I wanted to call it like:
val a:Int = 100 atMost 25
How would I write a function like that?
Also, what other styles of functions like this can you create? Like reading from left, reading from right side possible?
So 100 atMost 25 will always be translated by the compiler as 100.atMost(25).
So, we can reformulate your questions as "how we can add an additional method to an existing class", and the answer to that question would be extension methods (as a general programming concept) and implicit classes (as the technique we can use in Scala to model that).
// AnyVal to avoid instantiation cost & private val to hide an useless actual extension method.
implicit class IntOps (private val actual: Int) extends AnyVal {
def atMost(limit: Int): Int = max(actual, limit)
}
If that implicit is in scope, you can 100 atMost 25.
Also, what other styles of functions like this can you create? Like reading from left, reading from right side possible?
The other two important syntactic rules are.
Unary methods.
And right-associative methods.
For the first ones, you have to name them like unary_{S} where {S} is replaced by a single character which will be the unary symbol.
So a method defined as unary_! is to be called like: !true, which the compiler expands as true.unary_!().
For the second ones, if the method name ends with : then that method is called in the right operand instead of on the left.
So a method defined as ++: is to be called like foo ++: bar, which the compiler expands as bar.++:(foo).
Luis Miguel Mejía Suárez explained how to add a method to an existing class using an implicit class in Scala 2.
I would like to add that Scala 3 will introduce a new syntax for this:
extension (actual: Int)
def atMost(limit: Int): Int = max(actual, limit)
As you can see, there is no longer a need to create a new class for this use case. So it's more convenient because your don't have to come up with a name, your editor's type search won't be cluttered with these pseudo classes, there will be no useless allocations etc..
Scala 3 will be released before the end of the year, so it's time to start preparing :-)

How to have generic numeric type in scala for addition and multiplication?

I'm trying to implement generic numbers in scala that support addition and multiplication, can pattern match to any number and aren't restricted to any one type like Int, Double, etc. I looked up the docs and found that java.lang.Number fits the last criteria, i.e, any number pattern matched against java.lang.Number passes. So I quickly wrote up this implementation:
case class Number(num: java.lang.Number) {
def +(that: Number) = Number(this.num + that.num)
def *(that: Number) = Number(this.num * that.num)
}
However, as it turns out, java.lang.Number does not have the methods + and *. So I'm not sure how to implement this now. A professor suggested looking into typeclasses and the spire library, but I'm still having trouble.
Ideally, what I would like to have would be something like this
Number[A] + Number[A] returns Number[A]
Number[A] + Number[B] return Number[Finest type containing both A and B]
I'd be much obliged if someone could help me out with this. Thanks. :)
Scala has a typeclass for this called Numeric with implementations for the usual JVM number types.
note: it doesn't satisfy the Number[A] + Number[B] scenario
Examples Below
If you want to define your own number type, e.g.
case class RationalNumber(numerator: Int, denominator: Int)
Then you would also implement a Numeric instance for it
object RationalNumeric extends Numeric[RationalNumber] {
// implement the abstract methods
}
Some scala library methods (e.g. List's sum: def sum[B >: A](implicit num: Numeric[B]): B) take an implicit Numeric instance, so if you introduce an implicit reference to RationalNumeric, you could do something like:
List(RationalNumber(1,2), RationalNumber(2,3)).sum
Also, Numeric defines an implicit upgrade that adds operators to its class, so you could do this:
import RationalNumeric._
val sum = RationalNumber(1,2) + RationalNumber(2,3)

Can Scala apply multiple implicit conversions in one expression? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How can I chain implicits in Scala?
Can Scala apply multiple implicit conversions in one expression?
Consider this simple example:
case class Wrapper(s: String)
case class WrapperWrapper(w: Wrapper)
implicit def string2Wrapper(s: String) = Wrapper(s)
implicit def wrapper2WrapperWrapper(w: Wrapper) = WrapperWrapper(w)
// implicit conversation --> w = string2Wrapper("w")
val w: Wrapper = "w"
// implicit conversation --> ww = wrapper2WrapperWrapper(w)
val ww: WrapperWrapper = w
// does NOT compile!
// ideally --> sad = wrapper2WrapperWrapper(string2Wrapper("ww"))
val sad: WrapperWrapper = "ww"
Is there any way to get the "double" conversion in the last line to work?
I can help things along by defining another implicit like:
implicit def string2WrapperWrapper(s:String) = wrapper2WrapperWrapper(s)
but it seems like that shouldn't be necessary...
I'm afraid I don't have a concise reference to hand (the answer is scattered through 6.26 and chapter 7 of The Scala Language Specification), but the answer is no.
This is due to practicality - double implicit conversions would square the number of possible conversions available, greatly increasing the chance of collisions and making it harder to work out exactly what would happen with a given conversion.
It's not ideal that you have to declare the String to WrapperWrapper conversion yourself; but given how rarely you need to do this in practice, compared to the potential confusion of double implicits, I do consider it the lesser of two evils.
You can coerce the sequence of conversions fairly concisely:
scala> val sad: WrapperWrapper = ("ww": Wrapper)
sad: WrapperWrapper = WrapperWrapper(Wrapper(ww))
As explained by #Andrzej Doyle, two conversions at a time magnifies the risk of accidental conversions happening and so it is dissallowed.

How do I implement a generic mathematical function in Scala

I'm just getting started with Scala and something which I think should be easy is hard to figure out. I am trying to implement the following function:
def square(x:Int):Int = { x * x }
This works just fine, but if I want to try to make this function work for any kind of number I would like to be able to do the following:
def square[T <: Number](x : T):T = { x * x }
This complains and says: error: value * is not a member of type parameter T
Do I need to implement a trait for this?
That was one of my first questions in Stack Overflow or about Scala. The problem is that Scala maintains compatibility with Java, and that means its basic numeric types are equivalent to Java's primitives.
The problem arises in that Java primitives are not classes, and, therefore, do not have a class hierarchy which would allow a "numeric" supertype.
To put it more plainly, Java, and, therefore, Scala, does not see any common grounds between a Double's + and a an Int's +.
The way Scala finally got around this restriction was by using Numeric, and its subclasses Fractional and Integral, in the so-called typeclass pattern. Basically, you use it like this:
def square[T](x: T)(implicit num: Numeric[T]): T = {
import num._
x * x
}
Or, if you do not need any of the numeric operations but the methods you call do, you can use the context bound syntax for type declaration:
def numberAndSquare[T : Numeric](x: T) = x -> square(x)
For more information, see the answers in my own question.
You can define square as:
def square[T: Numeric](x: T): T = implicitly[Numeric[T]].times(x,x)
This approach has the advantage that it will work for any type T that has an implicit conversion to Numeric[T] (i.e. Int, Float, Double, Char, BigInt, ..., or any type for which you supply an implicit conversion).
Edit:
Unfortunately, you'll run into trouble if you try something like List(1,2,3).map(square) (specifically, you'll get a compile error like "could not find implicit value for evidence parameter of type Numeric[T]". To avoid this issue, you can overload square to return a function:
object MyMath {
def square[T: Numeric](x: T) = implicitly[Numeric[T]].times(x,x)
def square[T: Numeric]: T => T = square(_)
}
Hopefully someone with a better understanding of the type inferencer will explain why that is.
Alternatively, one can call List(1,2,3).map(square(_)), as Derek Williams pointed out in the scala-user mailing list thread.