2016-08-24 50 views
2

即使在了解了Scala中的静态超载后(What is Scala's static overloading rule?),我仍然无法将其用于<:<类。
此类用来检查子类,并在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 } 

然而,当我写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隐含的实例?为什么它在第二个例子中表现不同?

回答

0

您可以使用打印选项卡完成,看看类型:

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都不符合另一个(因为类型params的对偶和共同方差)。否则,一个val会被选为更具体。

编辑:您可以使用-Ytyper-debug来观察类型推断,它是如何选择未指定的类型arg。在这里,推断$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],它同样会使用$conforms[X]

+0

对不起,但无法理解你的答案。通过类型为scala.Predef。$ conforms [Y],您是否回答了我的第一个问题,指出隐式发现是<:<[Y,Y],意思是子类?如果是的话,为什么这一个而不是另一个?我同意你可以在Y => X的地方使用Y => Y,但是你不能使用X => X吗?什么打破了对称? – user2759511

+0

@ user2759511不知道为什么你仍然感到困惑,但这个类似的字眼答案可能会有所帮助。 HTTP://计算器。COM /问题/ 36035759 /如何 - 做最斯卡拉编译器,合成隐证据,与 –

+0

我想你混淆类型推断(由推论提供什么类型的ARG)与重载(有一个与<不超载: <)。 –