passing & using an implicit function without defining it - scala

I have not defined the function ev anywhere. Then, how come the below code works? Don't implicits have to be defined somewhere in scope for them to be used?
def same[T, U](x: U)(implicit ev: U => T): T = {ev(x)}
same(2) // 2

Any time you have questions like this, a good place to start is by using the Scala reflection API in the REPL to ask the compiler what's going on:
scala> import scala.reflect.runtime.universe.{ reify, showCode }
import scala.reflect.runtime.universe.{reify, showCode}
scala> def same[T, U](x: U)(implicit ev: U => T): T = ev(x)
same: [T, U](x: U)(implicit ev: U => T)T
scala> showCode(reify(same(2)).tree)
res0: String = $read.same(2)(Predef.$conforms)
So ev is provided by Predef.$conforms, an implicit method that will give you an instance of A <:< A for any A, where <:< extends Function1.
So that's one clue. Figuring out the rest requires thinking a little about type inference. When you call same(2), the compiler figures out that the expression 2 has type Int, and infers that U is Int. Next it needs to figure out what T is, and to do that it goes looking for implicit functions from Int to x for some type x.
This is where $conforms comes in. It's the only such method in scope, so the compiler chooses it, which means that ev is of type Int => Int and T has to be Int, and you're done.

Related

Lifting Functions using Cats Functor

with Cats, I can write this simple program
def foo(x: Int) = x + 1
val bar = Functor[Future](foo)
and Now I can do a bar(future(1)) and get a Future.Success(2) as a result. Very good.
But suppose my function was
def foo[T](x: T)(implicit m: Manifest[T]) : String = {...}
Now if I try to lift this function
def futureFoo = Functor[Future].lift(foo)
I get a compiler error No Manifest available for T.
So how do I lift this function?
I searched and found this thread (which is for scalaz)
Lifting a function which takes implicit parameter using functor (Scalaz7)
But I still couldn't create anything which worked for me. I tried
val futureFoo = Functor[T].lift2(foo[T] _)
but this doesn't compile
Functions in Scala cannot have implicit parameters, so when you try to eta-expand a method with an implicit parameter into a function, the implicit needs to be resolved before the function itself is applied. That is, at the time of eta-expansion. The compiler doesn't have a generic Manifest[T] in scope, but futureFoo can require one.
def foo[T](x: T)(implicit m: Manifest[T]) : String = ""
scala> def optionFoo[T: Manifest] = Functor[Option].lift(foo[T] _)
optionFoo: [T](implicit evidence$1: Manifest[T])Option[T] => Option[String]
I used Option because I didn't have a Functor[Future] readily available, the the same concept applies. Note that in order to use this, you'll need to supply the type parameter manually for it to return the correct function.
scala> optionFoo[Int].apply(Option(1))
res2: Option[String] = Some()

A => Class[A] using ClassTag?

Looking at ClassTag#runtimeClass, it has a return type of Class[_], i.e. a Class with, as I understand, a wildcard parameter.
I tried to implement a method: A => ClassTag[A]:
import scala.reflect._
scala> def f[A](x: A)(implicit ev: ClassTag[A]) = ev.runtimeClass
f: [A](x: A)(implicit ev: scala.reflect.ClassTag[A])Class[_]
But, the output of the def's definition is, as the docs show, Class[_].
Is it possible to change f such that its return type is Class[A]? If not, then why is it not possible?
Unless you change the signature of f, your only option is to cast the Class[_] to a Class[A].
There is literally only one method in the entire Scala standard library that returns a Class[A], and that is classOf. f[A] cannot be re-written to use classOf[A] since it is a special compiler method and is incompatible with generic type parameters that may not be classes. You would simply get an error:
scala> def f[A: ClassTag](x: A) = classOf[A]
<console>:10: error: class type required but A found
def f[A: ClassTag](x: A) = classOf[A]
^
The best you can get without casting is using x.getClass, but that will return a Class[_ <: A] (no ClassTag needed).
scala> def f[A](x: A): Class[_ <: A] = x.getClass
f: [A](x: A)Class[_ <: A]
scala> f(1)
res8: Class[_ <: Int] = class java.lang.Integer
scala> f(List(1, 2, 3))
res9: Class[_ <: List[Int]] = class scala.collection.immutable.$colon$colon
You might ask, why _ <: A?
The answer to that question is also the reason why your definition of f doesn't really make sense. If A is an Int, it makes sense to be able to return a Class[A] because Int is a class. But what if A is a List[Int]? List[Int] is not a class, it's a type. The class is List, but A != List, therefore we cannot return a Class[A] consistently. We can, however, have an upper-bound of A on the type parameter of Class.

How does the Scala compiler synthesize implicit evidence with `<:<`?

Given this (admittedly contrived) code fragment in Scala:
object Main extends App {
class X { def foo = 1 }
def f[A](value: A)(implicit ev: A <:< X) = { value.foo }
println(f(new X()))
}
What does the Scala compiler do to make this pass? I have looked at some code in Predef but I don't understand the implementation. Please give a detailed step by step explanation.
Callsite
Let's look at what the type inferencer does when you write:
f(new X())
It first has to figure out, what the template parameter A of f is. Type inference in Scala goes left to right in argument lists, so trivially (given new X is of type X), we get
f[X](new X)
Now the compiler needs to find an implicit value of type X <:< X (remember, A got resolved to X).
To find implicit values, the compiler looks in various places, amongst others your current scope (in which Predef._ is imported).
The compiler then finds Predef.$conforms:
implicit def $conforms[A]: A <:< A = // some implementation
So this can be used to produce a X <:< X, by invoking it with X as parameter:
f[X](new X)(Predef.$conforms[X])
The actual implementation of $conforms does not matter as far as the type checker is concerned.
Method Implementation
Now lets look at the implementation:
def f[A](value: A)(implicit ev: A <:< X) = { value.foo }
Value is of type A (so something unknown). You want to call foo on value. Since foo is not defined on A, the compiler is looking for an implicit function (or method) that converts A into something that has a foo.
There is such a thing in scope: ev (A <:< B extends A => B).
Therefore, the compiler inserts an implicit conversion using ev:
ev(value).foo
Small Note About Variance
As you might have noticed, <:< is variant in its parameters: <:<[-From, +To]. This can be used to generate actual subtyping evidences. Consider:
class A
class B extends A
val ev1: A <:< A = conforms
val ev2: B <:< A = ev1 // makes sense, works because of variance
// Also
val ev3: B <:< B = conforms
val ev4: B <:< A = ev3 // makes sense, works because of variance
This is notably the reason, why there is no need for a conforms method with two type parameters. Further, note that this behavior is specifically not wanted for =:= (since this is type equivalence), so it is invariant.

How does the <:< operator work in Scala?

In Scala there's a class <:< that witnesses a type constraint. From Predef.scala:
sealed abstract class <:<[-From, +To] extends (From => To) with Serializable
private[this] final val singleton_<:< = new <:<[Any,Any] { def apply(x: Any): Any = x }
implicit def $conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A]
An example of how it's used is in the toMap method of TraversableOnce:
def toMap[T, U](implicit ev: A <:< (T, U)): immutable.Map[T, U] =
What I don't understand is how this works. I understand that A <:< B is syntactically equivalent to the type <:<[A, B]. But I don't get how the compiler can find an implicit of that type if and only if A <: B. I assume that the asInstanceOf call in the definition of $conforms is making this possible somehow, but how? Also, is it significant that a singleton instance of an abstract class is used, instead of just using an object?
Suppose we've got the following simple type hierarchy:
trait Foo
trait Bar extends Foo
We can ask for proof that Bar extends Foo:
val ev = implicitly[Bar <:< Foo]
If we run this in a console with -Xprint:typer, we'll see the following:
private[this] val ev: <:<[Bar,Foo] =
scala.this.Predef.implicitly[<:<[Bar,Foo]](scala.this.Predef.$conforms[Bar]);
So the compiler has picked $conforms[Bar] as the implicit value we've asked for. Of course this value has type Bar <:< Bar, but because <:< is covariant in its second type parameter, this is a subtype of Bar <:< Foo, so it fits the bill.
(There's some magic involved here in the fact that the Scala compiler knows how to find subtypes of the type it's looking for, but it's a fairly generic mechanism and isn't too surprising in its behavior.)
Now suppose we ask for proof that Bar extends String:
val ev = implicitly[Bar <:< String]
If you turn on -Xlog-implicits, you'll see this:
<console>:9: $conforms is not a valid implicit value for <:<[Bar,String] because:
hasMatchingSymbol reported error: type mismatch;
found : <:<[Bar,Bar]
required: <:<[Bar,String]
val ev = implicitly[Bar <:< String]
^
<console>:9: error: Cannot prove that Bar <:< String.
val ev = implicitly[Bar <:< String]
^
The compiler tries the Bar <:< Bar again, but since Bar isn't a String, this isn't a subtype of Bar <:< String, so it's not what we need. But $conforms is the only place the compiler can get <:< instances (unless we've defined our own, which would be dangerous), so it quite properly refuses to compile this nonsense.
To address your second question: the <:<[-From, +To] class is necessary because we need the type parameters for this type class to be useful. The singleton Any <:< Any value could just as well be defined as an object—the decision to use a val and an anonymous class is arguably a little simpler, but it's an implementation detail that you shouldn't ever need to worry about.

what's different between <:< and <: in scala

I already know that:
<: is the Scala syntax type constraint
while <:< is the type that leverage the Scala implicit to reach the type constrait
for example:
object Test {
// the function foo and bar can have the same effect
def foo[A](i:A)(implicit ev : A <:< java.io.Serializable) = i
foo(1) // compile error
foo("hi")
def bar[A <: java.io.Serializable](i:A) = i
bar(1) // compile error
bar("hi")
}
but I want to know when we need to use <: and <:< ?
and if we already have <:, why we need <:< ?
thanks!
The main difference between the two is, that the <: is a constraint on the type, while the <:< is a type for which the compiler has to find evidence, when used as an implicit parameter. What that means for our program is, that in the <: case, the type inferencer will try to find a type that satisfies this constraint. E.g.
def foo[A, B <: A](a: A, b: B) = (a,b)
scala> foo(1, List(1,2,3))
res1: (Any, List[Int]) = (1,List(1, 2, 3))
Here the inferencer finds that Int and List[Int] have the common super type Any, so it infers that for A to satisfy B <: A.
<:< is more restrictive, because the type inferencer runs before the implicit resolution. So the types are already fixed when the compiler tries to find the evidence. E.g.
def bar[A,B](a: A, b: B)(implicit ev: B <:< A) = (a,b)
scala> bar(1,1)
res2: (Int, Int) = (1,1)
scala> bar(1,List(1,2,3))
<console>:9: error: Cannot prove that List[Int] <:< Int.
bar(1,List(1,2,3))
^
1. def bar[A <: java.io.Serializable](i:A) = i
<: - guarantees that instance of i of type parameter A will be subtype of Serializable
2. def foo[A](i:A)(implicit ev : A <:< java.io.Serializable) = i
<:< - guarantees that execution context will contains implicit value (for ev paramenter) of type A what is subtype of Serializable.
This implicit defined in Predef.scala and for foo method and it is prove if instance of type parameter A is subtype of Serializable:
implicit def conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A]
fictional case of using <:< operator:
class Boo[A](x: A) {
def get: A = x
def div(implicit ev : A <:< Double) = x / 2
def inc(implicit ev : A <:< Int) = x + 1
}
val a = new Boo("hi")
a.get // - OK
a.div // - compile time error String not subtype of Double
a.inc // - compile tile error String not subtype of Int
val b = new Boo(10.0)
b.get // - OK
b.div // - OK
b.inc // - compile time error Double not subtype of Int
val c = new Boo(10)
c.get // - OK
c.div // - compile time error Int not subtype of Double
c.inc // - OK
if we not call methods what not conform <:< condition than all compile and execute.
There are definitely differences between <: and <:<; here is my attempt at explaining which one you should pick.
Let's take two classes:
trait U
class V extends U
The type constraint <: is always used because it drives type inference. That's the only thing it can do: constrain the type on its left-hand side.
The constrained type has to be referenced somewhere, usually in the parameter list (or return type), as in:
def whatever[A <: U](p: A): List[A] = ???
That way, the compiler will throw an error if the input is not a subclass of U, and at the same time allow you to refer to the input's type by name for later use (for example in the return type). Note that if you don't have that second requirement, all this isn't necessary (with exceptions...), as in:
def whatever(p: U): String = ??? // this will obviously only accept T <: U
The Generalized Type Constraint <:< on the other hand, has two uses:
You can use it as an after-the-fact proof that some type was inferred. As in:
class List[+A] {
def sum(implicit ev: A =:= Int) = ???
}
You can create such a list of any type, but sum can only be called when you have the proof that A is actually Int.
You can use the above 'proof' as a way to infer even more types. This allows you to infer types in two steps instead of one.
For example, in the above List class, you could add a flatten method:
def flatten[B](implicit ev: A <:< List[B]): List[B]
This isn't just a proof, this is a way to grab that inner type B with A now fixed.
This can be used within the same method as well: imagine you want to write a utility sort function, and you want both the element type T and the collection type Coll. You could be tempted to write the following:
def sort[T, Coll <: Seq[T]](l: Coll): Coll
But T isn't constrained to be anything in there: it doesn't appear in the arguments nor output type. So T will end up as Nothing, or Any, or whatever the compiler wants, really (usually Nothing). But with this version:
def sort[T, Coll](l: Coll)(implicit ev: Coll <:< Seq[T]): Coll
Now T appears in the parameter's types. There will be two inference runs (one per parameter list): Coll will be inferred to whatever was given, and then, later on, an implicit will be looked for, and if found, T will be inferred with Coll now fixed. This essentially extracts the type parameter T from the previously-inferred Coll.
So essentially, <:< checks (and potentially infers) types as a side-effect of implicit resolution, so it can be used in different places / at different times than type parameter inference. When they happen to do the same thing, stick to <:.
After some thinking, I think it has some different.
for example:
object TestAgain {
class Test[A](a: A) {
def foo[A <: AnyRef] = a
def bar(implicit ev: A <:< AnyRef) = a
}
val test = new Test(1)
test.foo // return 1
test.bar // error: Cannot prove that Int <:< AnyRef.
}
this menas:
the scope of <: is just in the method param generic tpye scope foo[A <: AnyRef]. In the example, the method foo have it's generic tpye A, but not the A in class Test[A]
the scope of <:< , will first find the method's generic type, but the method bar have no param generic type, so it will find the Test[A]'s generic type.
so, I think it's the main difference.