scala: tracing implicits selection and other code magics - scala

When trying to figure how a library works, implicit conversions are confusing. For example, looking at an expression like 'val foo: Foo = 1', what converts 1 to Foo?
Is it possible to instruct the scala library (or REPL) to print out the code paths that are executing while evaluating an expression?

You can add "-Xprint:typer" to the compiler command line (or "-Ybrowse:typer" for a swing GUI browser) to see the code with the conversions explicitly applied.

As an alternative to printing out the conversions, one must realize implicits can't just come out of the blue. You have to bring them into scope in some way. The alternatives are:
Explicit import statement. Watch out for import x.y._ when y is an object, as this is the only way to bring in an implicit into scope.
The object companion of the class that is being converted into something else.
The object companion of the target class, as long as that target is made explicit somehow (such as in your example).
Note that the object scala.Predef is all imported into scope by default, which is how Scala's default implicits get into scope.

scalac -print prints the code after implicit type conversions where applied.
class A{
val x : String = "hi" drop 1
}
Will result in:
package <empty> {
class A extends java.lang.Object with ScalaObject {
#remote def $tag(): Int = scala.ScalaObject$class.$tag(A.this);
private[this] val x: java.lang.String = _;
<stable> <accessor> def x(): java.lang.String = A.this.x;
def this(): A = {
A.super.this();
A.this.x = scala.this.Predef.forceRandomAccessCharSeq(
scala.this.Predef.stringWrapper("hi").drop(1));
()
}
}
}

Related

Could not find implicit value inside companion object in Scala Worksheet

I am trying to create a type class inside IntelliJ Scala Worksheet. So I started with trait like this
trait Show[A] {
def show(a : A) : String
}
and created a companion object
object Show {
def show[A](a: A)(implicit sh: Show[A]) = sh.show(a)
implicit val intCanShow: Show[Int] =
new Show[Int] {
def show(int: Int): String = s"int $int"
}
}
When I try
println(Show.show(20))
I get this error.
Error:(50, 26) could not find implicit value for parameter sh: Show[Int]
println(Show.show(20))
But when I take the intCanShow out of the object Show, it works fine. Why cannot scala acess the the implicit inside the object?
Implicit resolution tries companion objects so your code seems ok. However for an object to become a companion it must satisfy the following two requirements
A companion object is an object with the same name as a class or trait, and
is defined in the same source file as the associated class or trait.
The following warning means the second requirement is not satisfied:
defined object Show
warning: previously defined trait Show is not a companion to object Show.
Companions must be defined together; you may wish to use :paste mode for this.
To satisfy second requirement we have to use Plain evaluation model in Scala Worksheet, or :paste mode in Scala REPL.
Scala Worksheet Plain evaluation model
To define a companion object in IntelliJ Scala Worksheet change Run type to Plain like so
Show Worksheet Settings
Select tab Settings for *.sc
Change Run type from REPL to Plain
Scala REPL paste mode
As per #jwvh suggestion, make sure to enter paste mode
If a class or object has a companion, both must be defined in the same
file. To define companions in the REPL, either define them on the same
line or enter :paste mode.
as demonstrated here.
Your example appears to work as expected when run as a scala script.
With the following in a file named test.sh and marked executable
#!/usr/bin/env scala
trait Show[A] {
def show(a : A) : String
}
object Show {
def show[A](a: A)(implicit sh: Show[A]) = sh.show(a)
implicit val intCanShow: Show[Int] =
new Show[Int] {
def show(int: Int): String = s"int $int"
}
}
println(Show.show(20))
I observe
bash-3.2$ ./test.sh
int 20

Creating `**` power operator for Scala?

I quite like the ** syntax for pow, available in many languages (such as Python).
Is it possible to introduce this into Scala, without modifying the Scala 'base' code?
My attempt at an Int only one:
import scala.math.pow
implicit class PowerInt(i: Int) {
def `**`(n: Int, b: Int): Int = pow(n, b).intValue
}
(see it failing on IDEone)
this works for me: (problem#1 pow is defined on doubles, problem#2 extending anyval)
(also there is no point in having those backticks in the methodname?)
import scala.math.pow
object RichIntt {
implicit class PowerInt(val i:Double) extends AnyVal {
def ** (exp:Double):Double = pow(i,exp)
}
def main(args:Array[String])
{
println(5**6)
}
}
This answer is 2 years late, still for the benefit of others I'd like to point out that the accepted answer unnecessarily extends from AnyVal.
There is just a minor bug that needs to be fixed in the original answer. The def ** method needs only one parameter, i.e. the exponent as the base is already passed in the constructor and not two as in the original code. Fixing that and removing the backticks results in:
import scala.math.pow
implicit class PowerInt(i: Int) {
def ** (b: Int): Int = pow(i, b).intValue
}
Which works as expected as seen here.
Scala compiler will cast an Int to a PowerInt only if the method that is called on it is undefined. That's why you don't need to extend from AnyVal.
Behind the scenes, Scala looks for an implicit class whose constructor argument type is the same as the type of the object that is cast. Since the object can have only one type, implicit classes cannot have more than one argument in their constructor. Moreover, if you define two implicit classes with the same constructor type, make sure their functions have unique signatures otherwise Scala wouldn't know which class to cast to and will complain about the ambiguity.
There is a way to make the solution a little bit more generic using Numeric typeclass:
implicit class PowerOp[T: Numeric](value: T) {
import Numeric.Implicits._
import scala.math.pow
def **(power: T): Double = pow(value.toDouble(), power.toDouble())
}
This is my solution using recursion (so I don't need import scala.Math.pow):
object RichInt {
implicit class PowerInt(val base:Double) {
def ** (pow:Double):Double = if (pow==0) 1 else base*(base**(pow-1))
}
def main(args:Array[String]){
println(2.0**3.0) //8.0
println(2.0**0.0) //1.0
}
}

Why does an implicit conversion on the constructor require 'this'?

Consider the following typical Scala 'pimp' code:
class PimpedA(a:A){
def pimp() = "hi"
}
implicit def pimpA(a:A) = new PimpedA(a)
new A(){
pimp() //<--- does not compile
}
However, changing it to:
new A(){
this.pimp()
}
Makes it work.
Shouldn't it be the same to the Scala compiler?
EDIT : Is there any solution that can make it work without having to add the this.?
Not at all. For it to work, pimp needs to be either an object or an imported member of a value, and it is neither. A class has an "implicit" import this._. It has not a mechanism that auto-prepends this to stuff to see if it compiles.
In this case you should give compiler a hint that pimp() is not a random function. When you write
this.pimp()
compiler know there isn't pimp function on class A so it's an error and before giving up it searches implicit conversion in scope and finds it.
pimpA(this).pimp()
And when you just call pimp() compiler doesn't know what object to pass to the pimpA(a: A) implicit function.
UPDATE
It is hard to understand what is your goal. I can only suggest to make PimpedA a typeclass (Pimp[T] in this example).
trait Pimp[T] {
def action(p: T): String
}
implicit object PimpA extends Pimp[A] {
override def action(p: A) = "some actions related to A"
}
def pimp[T: Pimp](p: T) = implicitly[Pimp[T]].action(p)
class A {
val foo = pimp(this)
}
scala> new A foo
res2: String = some actions related to A

Specs implicit conversion conflicts with Scala Predef

I have a type alias in my code like so:
type Time = Double
And I often in both tests and in applications pass Long values to functions that use this type. For instance:
def at(time : Time) : T = {
// Do Something
}
at(System.currentTimeMillis)
This code works fine unless run in my tests where I get the following error:
found : Long
required: com.github.oetzi.echo.Echo.Time
Note that implicit conversions are not applicable because they are ambiguous:
both method long2double in object Predef of type (x: Long)Double
and method longToDouble in trait NumericBaseMatchers of type (s: Long)Double
are possible conversion functions from Long to com.github.oetzi.echo.Echo.Time
After looking up NumericBaseMatchers it seems its part of the Specs testing framework (my tests are written in Specs 1). I tried running code to get the error in the interpreter and it was fine out side of the tests.
Is there any way I can somehow remove the ambiguity so I can pass Long to values to a Double/Time function? Why does Specs try and create its own LongToDouble conversion when Scala already provides this?
If you want to deactivate an inherited implicit conversion you can do this:
override def longToDouble(s: Long) = super.longToDouble(s)
For convenience if you add it to a new trait, you can mix-in your trait to your specification when needed:
trait NoConversion {
override def longToDouble(s: Long) = super.longToDouble(s)
}
class MySpecification extends NoConversion {
...
}
Try unimporting one of them.
import NumericBaseMatchers.{longToDouble => _}

Scala: Implicit parameter resolution precedence

Suppose we have implicit parameter lookup concerning only local scopes:
trait CanFoo[A] {
def foos(x: A): String
}
object Def {
implicit object ImportIntFoo extends CanFoo[Int] {
def foos(x: Int) = "ImportIntFoo:" + x.toString
}
}
object Main {
def test(): String = {
implicit object LocalIntFoo extends CanFoo[Int] {
def foos(x: Int) = "LocalIntFoo:" + x.toString
}
import Def._
foo(1)
}
def foo[A:CanFoo](x: A): String = implicitly[CanFoo[A]].foos(x)
}
In the above code, LocalIntFoo wins over ImportedIntFoo.
Could someone explain how it's considered more specific using "the rules of static overloading resolution (§6.26.3)"?
Edit:
The name binding precedence is a compelling argument, but there are several issues unresolved.
First, Scala Language Reference says:
If there are several eligible arguments which match the implicit parameter’s type, a most specific one will be chosen using the rules of static overloading resolution (§6.26.3).
Second, name binding precedence is about resolving a known identifier x to a particular member pkg.A.B.x in case there are several variable/method/object named x in the scope. ImportIntFoo and LocalIntFoo are not named the same.
Third, I can show that name binding precedence alone is not in play as follows:
trait CanFoo[A] {
def foos(x: A): String
}
object Def {
implicit object ImportIntFoo extends CanFoo[Int] {
def foos(x: Int) = "ImportIntFoo:" + x.toString
}
}
object Main {
def test(): String = {
implicit object LocalAnyFoo extends CanFoo[Any] {
def foos(x: Any) = "LocalAnyFoo:" + x.toString
}
// implicit object LocalIntFoo extends CanFoo[Int] {
// def foos(x: Int) = "LocalIntFoo:" + x.toString
// }
import Def._
foo(1)
}
def foo[A:CanFoo](x: A): String = implicitly[CanFoo[A]].foos(x)
}
println(Main.test)
Put this in test.scala and run scala test.scala, and it prints out ImportIntFoo:1.
This is because static overloading resolution (§6.26.3) says more specific type wins.
If we are pretending that all eligible implicit values are named the same, LocalAnyFoo should have masked ImportIntFoo.
Related:
Where does Scala look for implicits?
This is a great summary of implicit parameter resolution, but it quotes Josh's nescala presentation instead of the spec. His talk is what motivated me to look into this.
Compiler Implementation
rankImplicits
I wrote my own answer in the form of a blog post revisiting implicits without import tax.
Update: Furthermore, the comments from Martin Odersky in the above post revealed that the Scala 2.9.1's behavior of LocalIntFoo winning over ImportedIntFoo is in fact a bug. See implicit parameter precedence again.
1) implicits visible to current invocation scope via local declaration, imports, outer scope, inheritance, package object that are accessible without prefix.
2) implicit scope, which contains all sort of companion objects and package object that bear some relation to the implicit's type which we search for (i.e. package object of the type, companion object of the type itself, of its type constructor if any, of its parameters if any, and also of its supertype and supertraits).
If at either stage we find more than one implicit, static overloading rule is used to resolve it.
Update 2: When I asked Josh about Implicits without Import Tax, he explained to me that he was referring to name binding rules for implicits that are named exactly the same.
From http://www.scala-lang.org/docu/files/ScalaReference.pdf, Chapter 2:
Names in Scala identify types, values, methods, and classes which are
collectively called entities. Names are introduced by local definitions
and declarations (§4), inheritance (§5.1.3), import clauses (§4.7), or
package clauses (§9.2) which are collectively called bindings.
Bindings of different kinds have a precedence defined on them:
1. Definitions and declarations that are local, inherited, or made available by a package clause in the same compilation unit where the
definition occurs have highest precedence.
2. Explicit imports have next highest precedence.
3. Wildcard imports have next highest precedence.
4. Definitions made available by a package clause not in the compilation unit where the definition occurs have lowest precedence.
I may be mistaken, but the call to foo(1) is in the same compilation unit as LocalIntFoo, resulting in that conversion taking precedence over ImportedIntFoo.
Could someone explain how it's considered more specific using "the
rules of static overloading resolution (§6.26.3)"?
There's no method overload, so 6.26.3 is utterly irrelevant here.
Overload refers to multiple methods with the same name but different parameters being defined on the same class. For example, method f in the example 6.26.1 is overloaded:
class A extends B {}
def f(x: B, y: B) = . . .
def f(x: A, y: B) = . . .
val a: A
val b: B
Implicit parameter resolution precedence is a completely different rule, and one which has a question and answer already on Stack Overflow.