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)
Related
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.
So, implicit precedence is based on two factors: one is about the scope of declaration itself having precedence (scope A extending scope/trait B, or scope A being a companion object of a type extended from a type with scope B as its companion object). The other simply mentions that declaration A is more specific than declaration B. Now, when reading it for the first time I had several possible interpretations in mind, especially considering potential parameters (implicit and not) of implicit method and type parameters. Experience seemed to teach me that it means that the type of the returned value by declaration A, after all type inference/tapply, is a subtype of the return type of declaration B. So, this is fine:
class A
class B extends A
implicit val A = new A
implicit val B = new B
implicitly[A]
Why this doesn't compile, then?
implicit class A(val toInt :Int) {
def ! = (1 /: (2 to toInt))(_ * _)
}
implicit class B(i :Int) extends A(i)
1.!
When this does?
class A(val toInt :Int) {
def ! = (1 /: (2 to toInt))(_ * _)
}
class B(i :Int) extends A(i)
implicit val A = { i :Int => new A(i) }
implicit val B = { i :Int => new B(i) }
1.!
Is it another case of 'the compiler works in mysterious ways'?
Based on SIP-13 - IMPLICIT CLASSES proposal your declaration:
implicit class A(val toInt :Int) {
def ! = (1 /: (2 to toInt))(_ * _)
}
Will be transformed to something like:
class A(toInt: Int) {
...
}
implicit final def A(toInt: Int): A = new A(toInt);
And your B in its turn will be transformed to something like:
class B(i: Int) extends A(i) {
...
}
implicit final def B(i: Int): B = new B(i);
So you are basically declaring 2 implicit conversion methods with the same parameters which are ambiguous. While the last one is not ambiguous due to already mentioned "most specific" rule for implicit parameters resolution.
I am reading a Spark in Action book, I came across a construct that even after a while working with Scala I still can't understand. Here is the code (complete code) :
First we have a case class where RDD will be converted to DataFrame using this case class:
import java.sql.Timestamp
case class Post(
commentCount:Option[Int],
lastActivityDate:Option[java.sql.Timestamp],
ownerUserId:Option[Long],
body:String,
score:Option[Int],
... )
Then we define an object with implicit class
object StringImplicits {
implicit class StringImprovements(val s: String) {
import scala.util.control.Exception.catching
def toIntSafe = catching(classOf[NumberFormatException]) opt s.toInt
def toLongSafe = catching(classOf[NumberFormatException]) opt s.toLong
def toTimestampSafe = catching(classOf[IllegalArgumentException]) opt
Timestamp.valueOf(s)
}
}
Then we import the object which is already in scope for some reason and now looks like all String object has the three methods defined in StringImprovements
import StringImplicits._
def stringToPost(row: String): Post = {
val r = row.split("~")
Post(r(0).toIntSafe,
r(1).toTimestampSafe,
r(2).toLongSafe,
r(3),
...
}
Questions:
Why do we need to need to import an already in scope object?
Which statement exactly assigned these methods to the String object, this is so confusing?
Reading implicit classes doc it makes some sense but not everything is clear. For example how come this is a valid expression
scala> 5 times println("HI")
I understand if it was
IntWithTimes(5).time(println("HI"))
Implicits are sought among all methods and values that are visible in the current scope AND within companion objects of types that appear in the implicit type you are looking for.
implicit val a: A = ???
implicit val bc: B[C] = ???
// code here sees a and bc in implicit scope
def helper = {
implicit val c: C = ???
// code here sees a and bc and c in implicit scope
}
def anotherHelper = {
val a: A = ??? // overshades a
// code here sees b in implicit scope
}
object Helper {
implicit val e: E = ???
// code here sees a, bc and e in implicit scope
}
// implicits within helper, anotherHelper and Helper are not seen here
// though Helper one's can be imported with import Helper._
class D[T]
object {
implicit def provide[T](implicit a: T): D[T] = ???
}
class E
object E {
implicit val e: E = ???
}
class F
object F
// sees no implicits that are always available but
// if you require implicitly[E], E companion will be searched
// and implicit e will be found
// if you require implicitly[D[F]], both D and F companions
// will be searched, D.provide[F] will require implicit F,
// and no such implicit will be found - failure
If you asked for implicit A[B, C, (D, E), F[G]], then Scala would look into companions of A, B, C, D, E, Tuple2, F, G (if they exist). If this rule doesn't apply (your implicits aren't in companion, your type doesn't appear in sought implicit) you have to import them manually.
When Scala sees that you try to call a method on object that doesn't exists, it will try to convert it to some object which has this method. If you have some X type, it will look for implicits your X and returning some Y (implicit defs(x: X): Y and implicit val f: X => Y) and checking if that Y has this method.
Implicit class is basically a combination of a class and implicit method:
// implicit class Y(x: X) is the same as
class Y(x: X)
implicit def convert(x: X): Y = new Y(x)
which means that you can add some implicit conversions/classes from type X into X's companion and they will be always available.
In docs:
implicit class IntWithTimes(x: Int)
created implicit conversion from Int => IntWithTimes. String doesn't have times method, but there is a conversion Int => IntWithTimes in implicit scope imperted with import Helper._ (without it compilation would fail). Its result, IntWithTimes has the times method with the right signature, so the conversion is used.
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]].
I've been working on some scala code that was compiling fine, but somehow I've broken the implicit conversions and I can't work out what I've done wrong. Boiling it down to a very simple case, this code doesn't compile and the reason seems to be that I'm not importing the implicit conversions between Double and Numeric[Double]:
import scala.math.Numeric
import scala.math.Numeric._
import scala.math.Numeric.Implicits._
import Ordering.Implicits._
object ImplicitNumericConversions {
val v: Numeric[Double] = 3.0
}
I can fix this easily enough by providing my own function:
import scala.math.Numeric
object ImplicitNumericConversions {
def convertDoubleToNumeric(d: Double)(implicit num: Numeric[Double]): Numeric[Double] = num
val v: Numeric[Double] = convertDoubleToNumeric(3.0)
}
If I make the conversion function implicit then I get what I'm looking for:
import scala.math.Numeric
object ImplicitNumericConversions {
implicit def convertDoubleToNumeric(d: Double)(implicit num: Numeric[Double]): Numeric[Double] = num
val v: Numeric[Double] = 3.0
}
... but why don't the imports from scala.math.Numeric do this for me?
The actual problem that I'm working on looks like this:
class NumericRange[T <% Numeric[T]](val lower: T, val upper: T) { ... }
object NumericRange {
def apply[T](lower: T, upper: T)(implicit num: Numeric[T]) = {
import num._
new NumericRange[T](lower, upper)
}
}
... where the line creating the new NumericRange does not compile with these errors:
Multiple markers at this line
- No implicit view available from T => scala.math.Numeric[T].
- not enough arguments for constructor NumericRange: (implicit evidence$1: T => scala.math.Numeric[T])org.reductio.rtree.NumericRange[T]. Unspecified value parameter
evidence$1.
- not enough arguments for constructor NumericRange: (implicit evidence$1: T => scala.math.Numeric[T])org.reductio.rtree.NumericRange[T]. Unspecified value parameter
evidence$1.
- No implicit view available from T => scala.math.Numeric[T].
Numeric is a type class, which means you don't work with instances of Numeric[Double] in this way, but rather that you have a single implicit Numeric[Double] in scope that specifies how to perform numeric operations on Double (see my answer here for a related discussion of Ordering).
So you're looking for an implicit Numeric[T], not a T => Numeric[T]. And fortunately there is one of those in scope for Double, so you can just write:
class NumericRange[T: Numeric](val lower: T, val upper: T) { ... }
Or:
class NumericRange[T](val lower: T, val upper: T)(implicit
ev: Numeric[T]
) { ... }
The "context bound" in the first is just syntactic sugar for the implicit argument in the second.