2016-08-24 16 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)與重載(有一個與<不超載: <)。 –