Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 784
Zava Avatar asked Nov 07 '13 06:11

Zava


1 Answers

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))
                 ^
like image 144
drexin Avatar answered Sep 21 '22 10:09

drexin