Scala 2: Generic function that doubles a number - scala

Multiplying x and 2 doesn't work. Scala version is 2.13.8.
import Integral.Implicits._
object hello {
def f[T:Integral](x: T): T = x * 2
val x: Int = 1
f(x)
}
type mismatch;
found : Int(2)
required: T
def f[T:Integral](x: T): T = x * 2

You need to convert 2 into a T.
Thankfully, the instance of the Integral typeclass for T (which is passed implicitly thanks to [T: Integral] has a fromInt method which can convert an Int like 2 into a T:
def f[T: Integral](x: T): T = {
val two = implicitly[Integral[T]].fromInt(2) // summons the typeclass instance
x * two
}

Adding to what Levi mentioned, you'll need to import:
import scala.math.Integral.Implicits.infixIntegralOps
Still, you can simplify it to just:
def f[T: Integral](x: T): T = x * Integral[T].fromInt(2)
Taking advantage of the Integral companion object's apply method which takes an implicit of Integral[T] and returns it. It's exactly what implicitly does, only implicitly is more generic.

Related

Understanding Object Imports in Scala

As per the accepted answer in thread Using implicit objects within classes
if implicit objects are encapsulated within companion object of a generic type then there is no need to explicitly import properties and behaviour from object.
With that logic I am not able to understand why is below code not getting compiled after removing import num._
implicit class GenericMedian[T: Numeric](seq: Seq[T]) {
def median(): Double = {
val num: Numeric[T] = implicitly[Numeric[T]]
import num._
val medianPosition = seq.length / 2
seq.sortWith(gt) match {
case x if x.length % 2 != 0 => x(medianPosition).toDouble()
case x => (x(medianPosition).toDouble() + x(medianPosition - 1).toDouble()) / 2
}
}
}
Can someone throw some light on this concept?
Because uses of gt and toDouble that are imported from the num are not in the implicit position - i.e. toDouble is used explicitly and sortWith argument is not marked as implicit - so implicit resolution will not work for them.
So, the import num._ basically puts into explicit scope methods used later, specifically num.gt and another implicit Numeric[T].Ops which has toDouble implementation.
Consider the following example - median is rewritten to replace those two explicit uses with calls to functions that use implicit resolution:
implicit class GenericMedian[T: Numeric](seq: Seq[T]) {
def median(): Double = {
val medianPosition = seq.length / 2
sortWithImpl(seq) match {
case x if x.length % 2 != 0 => makeDouble(x(medianPosition))
case x => (
makeDouble(x(medianPosition)) +
makeDouble(x(medianPosition - 1))
) / 2
}
}
private def makeDouble(t: T)(implicit numeric: Numeric[T]): Double = numeric.toDouble(t)
private def sortWithImplicit(seq: Seq[T])(implicit numeric: Numeric[T]): Seq[T] = seq.sortWith(numeric.gt)
}
Note that no numeric instance is conjured from implicit scope makeDouble and sortWithImplicit use implicit resolution.
For deeper understanding, consider consulting with scala docs on implicits or this answer (in particular, "Accessing an Implicit Parameter Introduced by a Context Bound" section)

Basic implicit query

I am new to Scala, and trying to get my head around implicit wizardry. I want to understand why I am getting 2mysize with + function and the 2 * the length for * function?
implicit def addToStr(str: String) = str.size
scala> 2 * "mysize"
res4: Int = 12
scala> 2 + "mysize"
res3: String = 2mysize
Have a look at the ScalaDocs page for the Int API. The Int class has a +() method for adding a String.
abstract def +(x: String): String
But it has no *() method for multiplying a String. The compiler will always choose a defined function/method over an implicit. It will only go looking for an implicit solution as a last resort.
Implicit Conversions are only applied if the expression doesn't match the argument type of the function.
Example:
import scala.language.implicitConversions
implicit def strToInt(s: String):Int = s.size
def printStr(s: Int):Unit = {
println(s"Printing Int ${s}")
}
printStr("SSSS")
In the above case, the implicit method comes into picture, but if you define another method as shown below.
def printStr(s: String) = {
println(s"Printing String ${s}")
}
It will automatically use this method rather than implicit resolutions.
https://www.scala-lang.org/old/node/3911.html

How to define a function that works on unrelated types in Scala?

I'd like to define a function that applies * 2 to its argument, that works for all types where it's meaningful. I tried using structural types:
import scala.language.reflectiveCalls
def double[T](x: Any{def * (arg0: Int): T}) = x * 2
It works for strings:
scala> double("a")
res85: String = aa
But not for numbers:
scala> double(4)
java.lang.NoSuchMethodException: java.lang.Integer.$times(int)
at java.lang.Class.getMethod(Class.java:1778)
at .reflMethod$Method1(<console>:18)
at .double(<console>:18)
... 32 elided
Why do I get this error message?
Is it possible to do what I want using structural types?
Is it possible to do it in some other way?
Edit: By "do what I want" I mean working for already existing types, such as numbers and strings, not just for classes that I define myself.
* is translated to $times, structural type checks existence of * method, but (I suppose that's a bug) calls it's internal ($times) representations). That works for String, because there is $times for them.
This approach should work for methods with names that only contain letters.
```
import scala.language.reflectiveCalls
def double[T](x: Any{def test (arg0: Int): T}) = x.test(2)
class A { def test(i: Int) = i * 10 }
class B { def test(i: Int) = i * 20 }
scala> double(new A)
res0: Int = 20
scala> double(new B)
res1: Int = 40
Yes, idiomatic answer is typeclasses. You choose what exactly "meaningfulness" is. And they can be applied to any already existing class:
```
trait Multiply[A]{
def times(a: A, x: Int): A
}
implicit val MultString = new Multiply[String] { def times(a: String, x: Int) = a * x }
implicit val MultInt = new Multiply[Int] { def times(a: Int, x: Int) = a * x }
def double[T](t: T)(implicit mult: Multiply[T]) = mult.times(t, 2)
scala> double("aaaa")
res0: String = aaaaaaaa
scala> double(111)
res1: Int = 222
Also note that structural typing uses reflection => is quite slow.
You could always just overload the method. To make it work in the REPL you have to :paste it in as a block.
def double(s:String):String = s * 2
def double[N](n:N)(implicit ev: Numeric[N]):N = {
import Numeric.Implicits._
n * ev.fromInt(2)
}
double("this") // result: String = thisthis
double(3L) // result: Long = 6
One more possibility I've found is to use macros. As of Scala 2.11.8 they are still experimental and, according to Martin Odersky, won't survive in this form. The current synax is clumsy, but so far it is the only method that is completely DRY (* 2 is written only once, and the function works on all types that support this operation).
Regardless of whether this is the best solution, I'm posting it for the sake of completeness:
import reflect.macros.Context
def doubleImpl[T](c: Context)(x: c.Expr[T]): c.Expr[T] = {
import c.universe._
c.Expr(q"${x.tree} * 2")
}
def double[T](x: T): T = macro doubleImpl[T]

Constraining types in Scala's generics to accept any kind of Int

I want to write a function vaguely like:
def doubleit[A](a: A): A = {a + a}
But I want 'A' to mean any kind of Int, but not anything. Is there a way to give Scala a clue about what I want 'A' to mean?
def doubleit[A <: Int](a: A): A = {a + a}
is rejected by the compiler.
In plain Scala you can use type class Integral:
scala> def doubleit[A : Integral](a: A): A = implicitly[Integral[A]].plus(a, a)
doubleit: [A](a: A)(implicit evidence$1: Integral[A])A
scala> doubleit(2)
res0: Int = 4
scala> doubleit(BigInt(4))
res1: scala.math.BigInt = 8
Another possible syntax:
def doubleit[A](a: A)(implicit ev: Integral[A]): A = ev.plus(a, a)
ev is a commonly used name for those implicit parameters.
It is also possible to use normal operations like +, -, etc. instead of plus and minus:
def doubleit[A](a: A)(implicit ev: Integral[A]): A = {
import ev._
a + a
}
Or as per suggestion by #KChaloux, import from Integral.Implicits beforehand:
import Integral.Implicits._
def doubleit[A : Integral](a: A): A = a + a
If you want the function to support not only integers, but also Doubles, BigDecimals, etc. you can use Numeric instead of Integral:
import Numeric.Implcits._
def doubleit[A : Numeric](a: A): A = a + a
Explanation:
Writing [A : Integral] makes the function receive an implicit parameter of type Integral[A]. The implicits for all basic integral types are already defined in Scala, so you can use it with Int or BigInt straightaway. It is also possible to define new Integral types by defining a new implicit variable of type Integral[NewIntegralType] and implementing all the necessary methods.
The call to implicitly[Integral[A]] returns this implicit instance of Integral[A] which has method plus for addition, and other methods for performing other operations on integrals.

Shorter syntax for context bounds?

Is there a way to use shorter syntax when using context-bound type parameters? At the moment I have something like this
case class Vector2D[a : Numeric](x: a, y: a) {
val numA = implicitly[Numeric[a]]
def length2 = numA.plus(numA.times(x, x), numA.times(y, y))
}
and it makes more complex formulae unreadable.
Try this REPL session:
scala> case class Vector2D[T : Numeric](x: T, y: T) {
val numeric = implicitly[Numeric[T]]
import numeric._
def length2 = (x*x)+(y*y)
}
defined class Vector2D
scala> Vector2D(3,4).length2
res0: Int = 25
This is because Numeric contains an implicit conversion called mkNumericOps which you can import as shown above. If it didn't come out of the box, the way you could roll this yourself would be something like:
scala> implicit class NumericOps[T](val x: T) extends AnyVal { def +(y: T)(implicit n: Numeric[T]): T = n.plus(x, y)
| def *(y: T)(implicit n: Numeric[T]): T = n.times(x, y)
| }
defined class NumericOps
scala> case class Vector2D[a : Numeric](x: a, y: a) { def length2 = (x*x)+(y*y) }
defined class Vector2D
scala> Vector2D(3,4).length2
res0: Int = 25
If you make NumericOps not a value class (don't extend AnyVal) then the implicit Numeric can go on the constructor instead of each method, which might be better, or not really matter.
Anyway there's no need to write your own since Numeric already has mkNumericOps.
These "ops" classes are called the "enrich my library" pattern.
Numeric.Ops is here
and the implicit being imported to auto-create it is mkNumericOps on Numeric, here.
Just
import Numeric.Implicits._
then for every type that for which an implicit Numeric can be found
(importing just the NumericOps conversion of one Numeric instance as suggested by #Havoc P gives you finer control as to for which types operations are available, but most of the time, Numeric.Implicits should be fine)
On the more general question is there a shorter syntax when using context bounds type parameters: in general, there is not. It is up to the typeclass to provide some sugar to make it easy to use, as Numeric does here.
For instance, it is more or less customary to have an apply method in the companion object which makes getting the instance a little easier than with implicitly
object Ordering {
def apply[T](implicit ord: Ordering[T]): Ordering[T] = implicitly[Ordering[T]]
}
so that you can get the implicit just with e.g Ordering[Int], rather than implicitly[Ordering[Int]].