Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why class <:<[-From, +To] needs to extends (From => To) in scala standard library?

Tags:

scala

i am looking into scala's type level programming and have got some knowledge about it.But i have no idea why class <:< needs to extend from (From => To),i wrote the following code in REPL .

trait <:<[-T, +U] // just 'plain' generic trait

// an implicit object will looked up by compiler
implicit def implicitAgent[A]: <:<[A, A] = new <:<[A,A] {}

def myFunc[T,U](one:T, two:U)(implicit ev: T <:< U): Unit = {
    println(one, two)

class Base {
    override def toString: String = "base"
}

class Derived extends Base {
    override def toString: String = "Derived"
}

myFunc(new Derived, new Base)

and it works and prints:

(Derived,base)

So my question is what's the class <:<'s design decision?why it needs to extends From => To ?

like image 588
jatom Avatar asked Mar 09 '23 01:03

jatom


1 Answers

Because that way implicit ev: T <:< U also acts as an implicit conversion from T to U that can automatically upcast any value of type T to type U.

With <:< defined in Predef:

scala> trait Foo
defined trait Foo

scala> def myFunc[T](t: T)(implicit ev: T <:< Foo): Foo = t
myFunc: [T](t: T)(implicit ev: T <:< Foo)Foo

With your <:< :

scala> trait <:<[-T, +U]
defined trait $less$colon$less

scala> implicit def implicitAgent[A]: <:<[A, A] = new <:<[A,A] {}
implicitAgent: [A]=> A <:< A

scala> def myFunc[T](t: T)(implicit ev: T <:< Foo): Foo = t
<console>:14: error: type mismatch;
 found   : T
 required: Foo
       def myFunc[T](t: T)(implicit ev: T <:< Foo): Foo = t
                                                          ^

Once you have a proof that a value is an instance of U (i.e. its type T is a subtype of type U) it's very likely that you will want to use that value as an instance of U, otherwise why did you need the proof in the first place? If <:< is a function you can do that automatically.

like image 94
Jasper-M Avatar answered Mar 12 '23 06:03

Jasper-M