2013-02-20 118 views
7

所以我一直試圖通過twitter Scala school來學習Scala。但我目前卡在type bound examples之一。獲取Scala類型綁定錯誤:未找到:類型<%<

特別是,它是使用<%<類型關係運算符將類型綁定爲某種類型的可視類型。

當我在斯卡拉控制檯執行以下代碼:

scala> class Container[A](value: A) { def addIt(implicit evidence: A <%< Int) = 123 + value } 

...我收到以下錯誤:

<console>:7: error: not found: type <%< 
     class Container[A](value: A) { def addIt(implicit evidence: A <%< Int) = 123 + value } 
                    ^
<console>:7: error: overloaded method value + with alternatives: 
    (x: Double)Double <and> 
    (x: Float)Float <and> 
    (x: Long)Long <and> 
    (x: Int)Int <and> 
    (x: Char)Int <and> 
    (x: Short)Int <and> 
    (x: Byte)Int <and> 
    (x: String)String 
cannot be applied to (A) 
     class Container[A](value: A) { def addIt(implicit evidence: A <%< Int) = 123 + value } 

我的問題是,爲什麼斯卡拉解釋抱怨?

我一直在尋找通過Scala文檔,但我一直無法找到任何地方的操作員的信息。我可以看到斯卡拉學校是基於Scala 2.8.0創建的,而且我正在運行Scala 2.10.0 - 所以也許這已被刪除?如果是這種情況,爲什麼這看起來像一個有用的操作符?

+2

看起來這是不是在Scala 2.10,但我不確定爲什麼 - https://github.com/scala/scala/blob/v2.10.0/src/library/scala/Predef.scala #L1 – Impredicative 2013-02-20 15:37:58

+4

已在https://github.com/scala/scala/commit/e1780e9686914d835b295e125511368eeb1d0733#L0L350 – Debilski 2013-02-20 16:38:37

+1

中棄用!看起來正是我在下面猜測的原因。 – Impredicative 2013-02-20 16:58:11

回答

6

約束A <%< B斯卡拉2.8定義爲

sealed abstract class <%<[-From, +To] extends (From => To) 
    object <%< { 
    implicit def conformsOrViewsAs[A <% B, B]: A <%< B = new (A <%< B) {def apply(x: A) = x} 
    } 

所以,你可以隨時把它帶回的方式。不過,我猜它是過時的原因是綁定一個視圖只是要求一個隱函數從AB,而且也表現在已經是一個普遍的方式,尤其是約束一個完美的方法:

class Container[A](value: A) { def addIt(implicit evidence: A => Int) = 123 + value } 

順便說一下,值得注意的是,從定義中可以看出,它不是一個運算符,而是一個處於中綴位置的類。 =>也是如此,這是參考Function1類型構造函數的另一種方式。

+1

我一直在尋找官方推理背後的班級,但沒有任何運氣。你的猜測和任何人一樣好,足以滿足我的好奇心,謝謝! :) – jpihl 2013-02-20 16:30:44

2

this site,它表示A <%< B在Scala 2.9中已棄用。我不知道爲什麼,我同意這看起來有點奇怪,因爲它對我來說也是一個非常有用的操作符。

+2

正如在https://github.com/scala/scala/commit/e1780e9686914d835b295e125511368eeb1d0733#L0L350上的GitHub變更中所描述的那樣,由於A <> 2013-02-20 17:50:23

-1

正確的用法似乎是

class Container[A](value: A) { def addIt[A <% Int] = 123 + value } 

至於重載值,scala是選擇不解決不確定性;在這種情況下,你必須做出決定。

  • 你可以嘗試用調試:-Xprint:typer

  • ,或者你可以決定A確實Int使用class Container[A](value: A) { def addIt = 123 + value.asInstanceOf[Int] }或已經建議class Container[A](value: A) { def addIt(implicit evidence: A => Int) = 123 + value }無論是。它們是等價的。但是在這裏你是說A是一種Int;而不是A可以看作Int這就是<%所做的。

第二個選項不是微不足道的。考慮以下

scala> class Container[A](value: A) { def printIt[A <% Int] = println(123+" could be " + value) } 
defined class Container 

scala> val x = new Container("Love") 
x: Container[String] = [email protected] 

scala> x.printIt 
123 could be Love 

顯然"love"不是一個類型的Int因爲它是String,但它在這方面的完美的罰款:這就是爲什麼你應該小心使用A => Int

+0

頂部的代碼段絕對不是正確的用法! 'addIt'方法的類型參數'A'在類上映射參數'A',所以沒有增加這種情況。 – Impredicative 2013-02-20 17:08:25

+0

你的第二個例子僅僅是因爲一個全局隱式的'any2stringAdd',它可以讓任何類型轉換爲一個字符串來連接它 - 這完全是偶然的。另外,說'+ def addIt = 123 + value.asInstanceOf [Int]}'和'{def addIt(隱式證據:A => Int)= 123 + value}'是等價的。一種是不安全的演員,在編譯時會炸燬任何不是Int的子類型的東西。另一種是類型安全的,依賴於範圍內的隱式轉換。 – Impredicative 2013-02-20 17:13:08

+0

對不起,在運行時炸掉了,不是編譯時間。 – Impredicative 2013-02-21 09:06:46

相關問題