将scala静态重载规则应用于<:<

时间:2016-08-24 20:38:06

标签: scala implicit

即使在了解Scala(What is Scala's static overloading rule?)中的静态重载后,我仍然无法将其用于<:<类。 此类用于检查子类,并在Predef

中定义
sealed abstract class <:<[-From, +To] extends (From => To) with Serializable
private[this] final val singleton_<:< = new <:<[Any,Any] { def apply(x: Any): Any = x }

但是当我写A <:< B时,我不确定我是否使用<:<[A,A]<:<[B,B]的实例,因为遵循静态重载规则既不比另一个更具体。

我们首先尝试这一点,以确保它真的有效,用我的<:<替换mycic

class superC

class subC extends superC

abstract class mycic[-From,+To] extends ((From) => To) with Serializable

object Main extends App {
    implicit def FandT[A]: mycic[A,A] = new (mycic[A,A]) { def apply(x: A) ={x}}
    val e = implicitly[subC mycic superC]
    val a = new subC
    e.apply(a)
}

这很顺利。但是当我们尝试定义它正在使用的那个时:

class superC

class subC extends superC

abstract class mycic[-From,+To] extends ((From) => To) with Serializable

object Main extends App {
    implicit val FF : mycic[subC,subC] = new(mycic[subC,subC]){def apply(x:subC) ={println("FF");x}}
    implicit val TT : mycic[superC,superC] = new(mycic[superC,superC]){def apply(x:superC) ={println("TT");x}}
    val e = implicitly[subC mycic superC]
    val a = new subC
    e.apply(a)
}

我们收到以下编译错误:

Main.scala:10: error: ambiguous implicit values:
 both value TT in object Main of type => mycic[superC,superC]
 and value FF in object Main of type => mycic[subC,subC]
 match expected type mycic[subC,superC]
    val e = implicitly[subC mycic superC]
                          ^

在运行的代码中使用了哪个mycic隐式实例?为什么在第二个示例中它的行为有所不同?

1 个答案:

答案 0 :(得分:0)

您可以使用打印标签完成功能查看类型:

    $(".myselect").select2().select2("val", null);
    $('#test').val('<?php echo $previouschoice;?>').trigger('change');

(向右滚动以见证scala> def f[A,B](a: A, b: B)(implicit ev: A <:< B) = ev f: [A, B](a: A, b: B)(implicit ev: <:<[A,B])<:<[A,B] scala> trait X ; trait Y extends X defined trait X defined trait Y scala> f(null.asInstanceOf[Y], null.asInstanceOf[X]) //print $line3.$read.$iw.$iw.f[Y, X](null.asInstanceOf[$line4.$read.$iw.$iw.Y], null.asInstanceOf[$line4.$read.$iw.$iw.X])(scala.Predef.$conforms[Y]) // : <:<[Y,X] 作为隐式调用。)

scala.Predef.$conforms[Y]方法只是一个身份函数。由于功能的差异:

conforms

因此,如果scala> implicitly[(Y => Y) <:< (Y => X)] res0: <:<[Y => Y,Y => X] = <function1> scala> f(null.asInstanceOf[Y], null.asInstanceOf[X]) res1: <:<[Y,X] = <function1> scala> .apply(null.asInstanceOf[Y]) res2: X = null 符合Y,我可以使用X您要求的Y => Y。同样适用于Y => X

模棱两可的例子是因为两个隐式val都不符合另一个(因为类型参数的反对和共方差)。否则,一个val将被选为更具体的。

编辑:您可以使用<:<来观察类型推断,这是它选择未指定的类型arg的方式。在此,它推断-Ytyper-debug,因为预期类型为$conforms[Y]

<:<[Y,X]

如果您指定| | | | solving for (A: ?A, B: ?B) | | | | [search #1] start `[A, B](a: A, b: B)(implicit ev: <:<[A,B])<:<[A,B]`, searching for adaptation to pt=<:<[Y,X] (silent: value res0 in $iw) implicits disabled | | | | [search #1] considering $conforms | | | | solving for (A: ?A) | | | | [adapt] $conforms adapted to [A]=> <:<[A,A] based on pt <:<[Y,X] | | | | [search #1] success inferred value of type <:<[Y,X] is SearchResult(scala.Predef.$conforms[Y], ) | | | | |-- [A, B](a: A, b: B)(implicit ev: <:<[A,B])<:<[A,B] EXPRmode (site: value res0 in $iw) | | | | | \-> <:<[Y,X] ,则同样会使用f[X,X]