type constraints - How does the <:< operator work in Scala? -


in scala there's class <:< witnesses type constraint. predef.scala:

  sealed abstract class <:<[-from, +to] extends (from => to) serializable   private[this] final val singleton_<:< = new <:<[any,any] { def apply(x: any): = x }   implicit def $conforms[a]: <:< = singleton_<:<.asinstanceof[a <:< a] 

an example of how it's used in tomap method of traversableonce:

def tomap[t, u](implicit ev: <:< (t, u)): immutable.map[t, u] = 

what don't understand how works. understand a <:< b syntactically equivalent type <:<[a, b]. don't how compiler can find implicit of type if , if a <: b. assume asinstanceof call in definition of $conforms making possible somehow, how? also, significant singleton instance of abstract class used, instead of using object?

suppose we've got following simple type hierarchy:

trait foo trait bar extends foo 

we can ask proof bar extends foo:

val ev = implicitly[bar <:< foo] 

if run in console -xprint:typer, we'll see following:

private[this] val ev: <:<[bar,foo] =   scala.this.predef.implicitly[<:<[bar,foo]](scala.this.predef.$conforms[bar]); 

so compiler has picked $conforms[bar] implicit value we've asked for. of course value has type bar <:< bar, because <:< covariant in second type parameter, subtype of bar <:< foo, fits bill.

(there's magic involved here in fact scala compiler knows how find subtypes of type it's looking for, it's generic mechanism , isn't surprising in behavior.)

now suppose ask proof bar extends string:

val ev = implicitly[bar <:< string] 

if turn on -xlog-implicits, you'll see this:

<console>:9: $conforms not valid implicit value <:<[bar,string] because: hasmatchingsymbol reported error: type mismatch;  found   : <:<[bar,bar]  required: <:<[bar,string]        val ev = implicitly[bar <:< string]                           ^ <console>:9: error: cannot prove bar <:< string.        val ev = implicitly[bar <:< string]                           ^ 

the compiler tries bar <:< bar again, since bar isn't string, isn't subtype of bar <:< string, it's not need. $conforms place compiler can <:< instances (unless we've defined our own, dangerous), quite refuses compile nonsense.


to address second question: <:<[-from, +to] class necessary because need type parameters type class useful. singleton any <:< any value defined object—the decision use val , anonymous class arguably little simpler, it's implementation detail shouldn't ever need worry about.


Comments

Popular posts from this blog

python - TypeError: start must be a integer -

c# - DevExpress RepositoryItemComboBox BackColor property ignored -

django - Creating multiple model instances in DRF3 -