Scope of implicits - scala

As a follow up to my other question, see comments / questions in code:
case class Implicit(name: String)
def foo(implicit i: Implicit = null) = println(Option(i))
def bar1(implicit i: Implicit) {
foo // prints None
implicit val i = Implicit("J") // Why is call to foo above affected although this line comes after?
foo // prints Some(Implicit(I))
}
def bar2(implicit i: Implicit) {
foo // prints None
implicit val i = null
implicit val j = Implicit("J")
foo // prints None // Why? Should raise ambiguous implicits or at least choose j.
}
def bar3(implicit i: Implicit) {
foo // prints None
val i = null
implicit val j = Implicit("J")
foo // prints Some(Implicit(J)) // Now it works as I expected to work in bar2.
}
def bar4(implicit i: Implicit) { // That's how I expected to see bar1 working. A ugly hack here.
foo // prints Some(Implicit(I))
locally {
val i = null
implicit val j = Implicit("J")
foo // prints Some(Implicit(J))
}
}
val i = Implicit("I")
bar1(i)
bar2(i)
bar3(i)
bar4(i)

Your code suffers from name shadowing. The spec in chapter 2 says about this:
A binding has a scope in which the entity defined by a single name can be accessed using a simple name. Scopes are nested. A binding in some inner scope shadows bindings of lower precedence in the same scope as well as bindings of the same or lower precedence in outer scopes.
In your example, this means that with
def foo(implicit i: Implicit) = println(Option(i))
we have the following possibilities:
The implicit param i gets passed to foo because x would be a forward reference:
scala> def f(implicit i: Implicit) = {foo; implicit val x = Implicit("i")}
f: (implicit i: Implicit)Unit
Nothing can be passed to foo because parameter i is shadowed by the local value i which has higher precedence but can't be called because it is a forward reference.
scala> def f(implicit i: Implicit) = {foo; implicit val i = Implicit("i")}
<console>:11: error: could not find implicit value for parameter i: Implicit
def f(implicit i: Implicit) = {foo; implicit val i = Implicit("i")}
^
A value is shadowed when it has the same name, but it must not have the same type:
scala> def f(implicit i: Implicit) = {implicit val j = Implicit("i"); foo}
<console>:11: error: ambiguous implicit values:
both value i of type Implicit
and value j of type Implicit
match expected type Implicit
def f(implicit i: Implicit) = {implicit val j = Implicit("i"); foo}
^
scala> def f(implicit i: Implicit) = {val i = null; implicit val j = Implicit("i"); foo}
f: (implicit i: Implicit)Unit
There exists multiple implicits in scope, but one has higher precedence. In this case i has the higher precedence because Null <: Implicit
scala> def f(implicit i: Implicit) = {implicit val i = null; implicit val j = Implicit("i"); foo}
f: (implicit i: Implicit)Unit
Your definition of foo was declared with a default value for the implicit parameter. This doesn't change anything at the rules mentioned above, but the compiler can choose the default value when no other value is available.

Related

Alternative Syntax When Defining Implicit?

Given the following:
scala> trait Foo { def get: String = "get" }
defined trait Foo
I implemented it and made an implicit:
scala> case class FooImpl(x: String) extends Foo {
| override def get = s"got $x"
| }
defined class FooImpl
scala> implicit val fooImpl = FooImpl("yo")
fooImpl: FooImpl = FooImpl(yo)
Lastly, I tried to write a method that implicitly resolves a Foo, returning get on that implicitly resolved class.
scala> def f[A: Foo](x: A) = x.get
<console>:11: error: Foo does not take type parameters
def f[A: Foo](x: A) = x.get
^
<console>:11: error: value get is not a member of type parameter A
def f[A: Foo](x: A) = x.get
^
But I got the above errors.
So I re-wrote it using the implicit keyword:
scala> def f(implicit x: Foo): String = x.get
f: (implicit x: Foo)String
scala> f
res0: String = got yo
Is it possible to re-write this example to not explicitly specify the implicit keyword?
Note - it's possible that I'm confusing this notation with TypeTag under the section, Using a Context bound of a Type Parameter.
You are using the wrong syntax, what you want is an upper bound:
scala> def f[A <: Foo](x: A) = x.get
f: [A <: Foo](x: A)String
Where you're saying that A is a subtype of Foo and that tells the compiler that A does have a method called get.
The syntax you're using (:) means that there's an implicit conversion from A to Foo[A], the problem is that Foo doesn't take a type parameter, you can also check it into the REPL where the column syntax is translated to an implicit parameter:
scala> trait Foo2[T]
defined trait Foo2
scala> def g[T: Foo2](x: Int): Int = x
g: [T](x: Int)(implicit evidence$1: Foo2[T])Int

default type conversions from sub to supertype, zero parameter functions

I am trying to understand the mechanism with which scala implements default type converions from sub to super type in scala.Predef. From the literature I gathered that this is done with the function
implicit def conforms[A] = new A<:<A { def apply(a:A)=a }
The parameterless function conforms[A] returns the implicit conversion A=>B as its only
function value (as a callable of type A=>A and thus of type A=>B, whenver A<:B).
However when the compiler looks for an implicit type conversion it needs an implicit value
of type A=>B not a function returning such a value. Thus my question:
When looking for a default type conversion from A=>B, where A<:B, how does the compiler
get from the function conforms[A] to its unique value.
The implicit resolution seeks for subtypes too, A <: B => A => A <: A => B, as in List[Int] <: Seq[Int].
scala> :paste
// Entering paste mode (ctrl-D to finish)
implicit val x: List[Int] = List(1, 2, 3)
def f(implicit x: Seq[Int]): Int = x.head
f
// Exiting paste mode, now interpreting.
x: Seq[Int] = List(1, 2, 3)
f: (implicit x: Seq[Int])Int
res1: Int = 1
So when making type conversion we look for A => B with A <: B, and A => A fits.
I'm not sure if I understood you right, but the defs are followed while searching for value of the needed type. It doesn't matter whether function takes zero, one, or more parameters. For example with zero:
implicit def implicitList[A]: List[A] = List() //the only obvious case
scala> implicitly[Seq[Int]]
// res0: Seq[Int] = List()
Or two:
case class Foo(str: String)
case class Bar(str: String)
case class Quux(str: String)
implicit val foo = Foo("foo")
implicit val bar = Bar("bar")
// how to build quux:
implicit def quux(implicit foo: Foo, bar: Bar): Quux = Quux(foo.str + bar.str)
implicitly[Quux]
// res2: Quux = Quux(foobar)
If we add any of:
implicit def quux2(implicit quux: Quux): Quux = quux
implicit def quux3(implicit foo: Foo): Quux = Quux(foo.str)
implicit val quux4: Quux = Quux("quux")
implicit def quux5[A]: Quux = Quux("poly")
We make implicit resolution undecidable for Quux:
scala> implicitly[Quux]
<console>:29: error: ambiguous implicit values:
both method quux of type (implicit foo: Foo, implicit bar: Bar)Quux
and method quux2 of type (implicit quux: Quux)Quux
match expected type Quux
implicitly[Quux]
^
I.e. there could be only one def or val in scope returning the type we are interested. And that is easy to verify statically.
But they will work if any of those is the only one in scope.

Is providing explicitly the context bound possible in Scala?

In the following code:
def sum[A: Monoid](xs: List[A]): A = {
val m = implicitly[Monoid[A]]
xs.foldLeft(m.mzero)(m.mappend)
}
If I already have in my scope a Monoid[Int] that has mappend = _ + _, can I call my function with an explicit Monoid[Int] which has a different behavior? Or the only solution is to use a more verbose syntax with a second argument implicit monoid: Monoid[Int]?
The code exemple comes from this Scalaz tutorial: http://eed3si9n.com/learning-scalaz/sum+function.html
At the end the author shows an exemple of providing explicitly the Monoid, but he didn't use context bounds:
scala> val multiMonoid: Monoid[Int] = new Monoid[Int] {
def mappend(a: Int, b: Int): Int = a * b
def mzero: Int = 1
}
multiMonoid: Monoid[Int] = $anon$1#48655fb6
scala> sum(List(1, 2, 3, 4))(multiMonoid)
res14: Int = 24
Context bounds are nothing more than syntactic sugar.
The following:
def sum[A: Monoid](xs: List[A])
is extactly the same as:
def sum[A](xs: List[A])(implicit evidence: Monoid[A])
This means that regardless of the way you defined your sum method (either with a context bound or with an implicit parameter), you can explicitly pass the implicit parameter as in sum(List(1, 2, 3, 4))(multiMonoid)

Scala Macros: "cannot create TypeTag from a type T having unresolved type parameters"

I'm playing around with Scalas new macros and found this gist from akshaal. As it seams I did not quite get it.
Given the following trait (the fieldsMacro is more or less the same as in akshaal example)
case class Field[I <: AnyRef](name: String, get: I => Any)
type Fields[I <: AnyRef] = List[Field[I]]
trait FieldAccess {
import FieldMacors._
import Field._
import language.experimental.macros
def fields[T <: AnyRef]: Fields[T] = macro fieldsMacro[T]
def field[T <: AnyRef](name: String): Fields[T] = fields[T].headOption <-- does not work!
^
}
object FieldMacors {
import language.experimental.macros
import Field._
def fields[T <: AnyRef]: Fields[T] = macro fieldsMacro[T]
/**
* Get a list of fiels
*/
def fieldsMacro[T <: AnyRef: c.TypeTag](c: Context): c.Expr[Fields[T]] = {
import c.universe._
val instanceT = c.typeOf[T]
val fields = instanceT.members.filter(member => member.isTerm && !member.isMethod)
// transform an iterable of expr in a expr of list.
def foldIntoListExpr[T: c.TypeTag](exprs: Iterable[c.Expr[T]]): c.Expr[List[T]] =
exprs.foldLeft(reify { Nil: List[T] }) {
(accumExpr, expr) =>
reify { expr.splice :: accumExpr.splice }
}
val fieldAccessores = for (field <- fields) yield {
val name = field.name.toString.trim // Why is there a space at the end of field name?!
val nameExpr = c literal name
// Construct expression (x : $I) => x.$name
val getFunArgTree = ValDef(Modifiers(), newTermName("x"), TypeTree(instanceT), EmptyTree)
val getFunBodyTree = Select(Ident(newTermName("x")), newTermName(name))
val getFunExpr = c.Expr[T => Any](Function(List(getFunArgTree), getFunBodyTree))
reify {
Field[T](name = nameExpr.splice, get = getFunExpr.splice)
}
}
foldIntoListExpr(fieldAccessores)
}
}
the compiler complains about
'Cannot create TypeTag from a type T having unresolved type parameters'
How do I manage to get the T to the macro or must I implement another macro that uses the fieldsMacro
T: TypeTag context bound for a type parameter T means that you require type arguments provided in place of this parameter to be concrete (i.e. not contain references to untagged type parameters or abstract type members). Otherwise an error occurs.
Examples:
scala> val ru = scala.reflect.runtime.universe
ru # 6d657803: scala.reflect.api.JavaUniverse = scala.reflect.runtime.JavaUniverse#6d657803
scala> def foo[T: ru.TypeTag] = implicitly[ru.TypeTag[T]]
foo: [T](implicit evidence$1: reflect.runtime.universe.TypeTag[T])reflect.runtime.universe.TypeTag[T]
scala> foo[Int]
res0 # 7eeb8007: reflect.runtime.universe.TypeTag[Int] = TypeTag[Int]
scala> foo[List[Int]]
res1 # 7d53ccbe: reflect.runtime.universe.TypeTag[List[Int]] = TypeTag[scala.List[Int]]
scala> def bar[T] = foo[T] // T is not a concrete type here, hence the error
<console>:26: error: No TypeTag available for T
def bar[T] = foo[T]
^
scala> def bar[T] = foo[List[T]] // T being not concrete renders
// the entire compound type not concrete
<console>:26: error: No TypeTag available for List[T]
def bar[T] = foo[List[T]]
^
scala> def bar[T: TypeTag] = foo[T] // to the contrast T is concrete here
// because it's bound by a concrete tag bound
bar: [T](implicit evidence$1: reflect.runtime.universe.TypeTag[T])reflect.runtime.universe.TypeTag[T]
scala> bar[Int]
res2 # 7eeb8007: reflect.runtime.universe.TypeTag[Int] = TypeTag[Int]
scala> def bar[T: TypeTag] = foo[List[T]]
bar: [T](implicit evidence$1: reflect.runtime.universe.TypeTag[T])reflect.runtime.universe.TypeTag[List[T]]
scala> bar[Int]
res3 # 1a108c98: reflect.runtime.universe.TypeTag[List[Int]] = TypeTag[scala.List[Int]]
scala> bar[List[Int]]
res4 # 76d5989c: reflect.runtime.universe.TypeTag[List[List[Int]]] = TypeTag[scala.List[scala.List[Int]]]
Having a notion of concrete types to be enforcible at compile-time is useful. Having concrete type tags on by default is useful as well as described in https://issues.scala-lang.org/browse/SI-5884.
However as you've seen yourself, concrete type tags in macros can be a source of confusion, because typically macros should work both for concrete and non-concrete types. Therefore one should always use c.AbsTypeTag instead. Due to this reason we no longer allow c.TypeTag context bounds in 2.10.0-M7: https://github.com/scala/scala/commit/788478d3ab.
Edit. In 2.10.0-RC1 some AbsTypeTag has been renamed to WeakTypeTag. Everything else about type tags remains the same.

What is the Scala identifier "implicitly"?

I have seen a function named implicitly used in Scala examples. What is it, and how is it used?
Example here:
scala> sealed trait Foo[T] { def apply(list : List[T]) : Unit }; object Foo {
| implicit def stringImpl = new Foo[String] {
| def apply(list : List[String]) = println("String")
| }
| implicit def intImpl = new Foo[Int] {
| def apply(list : List[Int]) = println("Int")
| }
| } ; def foo[A : Foo](x : List[A]) = implicitly[Foo[A]].apply(x)
defined trait Foo
defined module Foo
foo: [A](x: List[A])(implicit evidence$1: Foo[A])Unit
scala> foo(1)
<console>:8: error: type mismatch;
found : Int(1)
required: List[?]
foo(1)
^
scala> foo(List(1,2,3))
Int
scala> foo(List("a","b","c"))
String
scala> foo(List(1.0))
<console>:8: error: could not find implicit value for evidence parameter of type
Foo[Double]
foo(List(1.0))
^
Note that we have to write implicitly[Foo[A]].apply(x) since the compiler thinks that implicitly[Foo[A]](x) means that we call implicitly with parameters.
Also see How to investigate objects/types/etc. from Scala REPL? and Where does Scala look for implicits?
implicitly is avaliable in Scala 2.8 and is defined in Predef as:
def implicitly[T](implicit e: T): T = e
It is commonly used to check if an implicit value of type T is available and return it if such is the case.
Simple example from retronym's presentation:
scala> implicit val a = "test" // define an implicit value of type String
a: java.lang.String = test
scala> val b = implicitly[String] // search for an implicit value of type String and assign it to b
b: String = test
scala> val c = implicitly[Int] // search for an implicit value of type Int and assign it to c
<console>:6: error: could not find implicit value for parameter e: Int
val c = implicitly[Int]
^
Here are a few reasons to use the delightfully simple method implicitly.
To understand/troubleshoot Implicit Views
An Implicit View can be triggered when the prefix of a selection (consider for example, the.prefix.selection(args) does not contain a member selection that is applicable to args (even after trying to convert args with Implicit Views). In this case, the compiler looks for implicit members, locally defined in the current or enclosing scopes, inherited, or imported, that are either Functions from the type of that the.prefix to a type with selection defined, or equivalent implicit methods.
scala> 1.min(2) // Int doesn't have min defined, where did that come from?
res21: Int = 1
scala> implicitly[Int => { def min(i: Int): Any }]
res22: (Int) => AnyRef{def min(i: Int): Any} = <function1>
scala> res22(1) //
res23: AnyRef{def min(i: Int): Int} = 1
scala> .getClass
res24: java.lang.Class[_] = class scala.runtime.RichInt
Implicit Views can also be triggered when an expression does not conform to the Expected Type, as below:
scala> 1: scala.runtime.RichInt
res25: scala.runtime.RichInt = 1
Here the compiler looks for this function:
scala> implicitly[Int => scala.runtime.RichInt]
res26: (Int) => scala.runtime.RichInt = <function1>
Accessing an Implicit Parameter Introduced by a Context Bound
Implicit parameters are arguably a more important feature of Scala than Implicit Views. They support the type class pattern. The standard library uses this in a few places -- see scala.Ordering and how it is used in SeqLike#sorted. Implicit Parameters are also used to pass Array manifests, and CanBuildFrom instances.
Scala 2.8 allows a shorthand syntax for implicit parameters, called Context Bounds. Briefly, a method with a type parameter A that requires an implicit parameter of type M[A]:
def foo[A](implicit ma: M[A])
can be rewritten as:
def foo[A: M]
But what's the point of passing the implicit parameter but not naming it? How can this be useful when implementing the method foo?
Often, the implicit parameter need not be referred to directly, it will be tunneled through as an implicit argument to another method that is called. If it is needed, you can still retain the terse method signature with the Context Bound, and call implicitly to materialize the value:
def foo[A: M] = {
val ma = implicitly[M[A]]
}
Passing a subset of implicit parameters explicitly
Suppose you are calling a method that pretty prints a person, using a type class based approach:
trait Show[T] { def show(t: T): String }
object Show {
implicit def IntShow: Show[Int] = new Show[Int] { def show(i: Int) = i.toString }
implicit def StringShow: Show[String] = new Show[String] { def show(s: String) = s }
def ShoutyStringShow: Show[String] = new Show[String] { def show(s: String) = s.toUpperCase }
}
case class Person(name: String, age: Int)
object Person {
implicit def PersonShow(implicit si: Show[Int], ss: Show[String]): Show[Person] = new Show[Person] {
def show(p: Person) = "Person(name=" + ss.show(p.name) + ", age=" + si.show(p.age) + ")"
}
}
val p = Person("bob", 25)
implicitly[Show[Person]].show(p)
What if we want to change the way that the name is output? We can explicitly call PersonShow, explicitly pass an alternative Show[String], but we want the compiler to pass the Show[Int].
Person.PersonShow(si = implicitly, ss = Show.ShoutyStringShow).show(p)
Starting Scala 3 implicitly has been replaced with improved summon which has the advantage of being able to return a more precise type than asked for
The summon method corresponds to implicitly in Scala 2. It is
precisely the same as the the method in Shapeless. The difference
between summon (or the) and implicitly is that summon can return a
more precise type than the type that was asked for.
For example given the following type
trait F[In]:
type Out
def f(v: Int): Out
given F[Int] with
type Out = String
def f(v: Int): String = v.toString
implicitly method would summon a term with erased type member Out
scala> implicitly[F[Int]]
val res5: F[Int] = given_F_Int$#7d0e5fbb
scala> implicitly[res5.Out =:= String]
1 |implicitly[res5.Out =:= String]
| ^
| Cannot prove that res5.Out =:= String.
scala> val x: res5.Out = ""
1 |val x: res5.Out = ""
| ^^
| Found: ("" : String)
| Required: res5.Out
In order to recover the type member we would have to refer to it explicitly which defeats the purpose of having the type member instead of type parameter
scala> implicitly[F[Int] { type Out = String }]
val res6: F[Int]{Out = String} = given_F_Int$#7d0e5fbb
scala> implicitly[res6.Out =:= String]
val res7: res6.Out =:= String = generalized constraint
However summon defined as
def summon[T](using inline x: T): x.type = x
does not suffer from this problem
scala> summon[F[Int]]
val res8: given_F_Int.type = given_F_Int$#7d0e5fbb
scala> summon[res8.Out =:= String]
val res9: String =:= String = generalized constraint
scala> val x: res8.Out = ""
val x: res8.Out = ""
where we see type member type Out = String did not get erased even though we only asked for F[Int] and not F[Int] { type Out = String }. This can prove particularly relevant when chaining dependently typed functions:
The type summoned by implicitly has no Out type member. For this
reason, we should avoid implicitly when working with dependently typed
functions.
A "teach you to fish" answer is to use the alphabetic member index currently available in the Scaladoc nightlies. The letters (and the #, for non-alphabetic names) at the top of the package / class pane are links to the index for member names beginning with that letter (across all classes). If you choose I, e.g., you'll find the implicitly entry with one occurrence, in Predef, which you can visit from the link there.