2013-02-20 7 views
7

Próbowałem nauczyć się Scala przez twitter Scala school. Ale obecnie utknąłem w jednym z ich type bound examples.Uzyskiwanie błędu związanego z typem Scala: nie znaleziono: typ <% <

W szczególności jest to ten, w którym typ może być widoczny jako określony typ, przy użyciu operatora relacji typu: <%<.

Kiedy wykonać następujący kod w moim konsoli Scala:

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

... otrzymuję następujące błędy:

<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 } 

Moje pytanie brzmi, dlaczego jest interpreter Scala skarżą?

Próbowałem przejrzeć dokumentację Scala, ale nie udało mi się znaleźć informacji o tym użytkowniku w dowolnym miejscu. Widzę, że szkoła Scala została stworzona na podstawie Scala 2.8.0, a ja używam Scala 2.10.0 - więc może to zostało usunięte? Jeśli tak, to dlaczego wydaje się, że jest to użyteczny operator?

+2

Wygląda na to, że tego nie ma w Scali 2.10, choć nie jestem do końca pewien dlaczego - https://github.com/scala/scala/blob/v2.10.0/src/library/scala/Predef.scala # L1 – Impredicative

+4

Został wycofany w https://github.com/scala/scala/commit/e1780e9686914d835b295e125511368eeb1d0733#L0L350 – Debilski

+1

Dobrze! Wygląda dokładnie na przyczynę, o której myślałem poniżej. – Impredicative

Odpowiedz

6

Ograniczenie A <%< B w Scala 2.8 definiuje się jako

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} 
    } 

więc zawsze można go przywrócić w ten sposób. Jednakże, zgaduję, że powodem jest to niezalecane jest to, że widok związany jest tylko z prośbą o domniemanym funkcji z A do B, a tam doskonale dobry sposób na wyrażenie tego szczególnego ograniczenia w sposób uogólniony już:

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

Na marginesie warto zauważyć, że nie jest to operator, ale klasa w pozycji "zaklinowana", jak widać z definicji. To samo dotyczy =>, który jest po prostu innym sposobem odwoływania się do konstruktora typu Function1.

+1

Szukałem trochę oficjalnego uzasadnienia usunięcia klasy, ale bez powodzenia. Twoje przypuszczenie jest tak dobre jak u każdego i wystarczy, aby zaspokoić moją ciekawość, dzięki! :) – jpihl

2

Na stronie this site podano, że A <%< B został przestarzały w wersji Scala 2.9. Nie wiem dlaczego, i zgadzam się, że wydaje się to trochę dziwne, ponieważ dla mnie wygląda również na całkiem użytecznego operatora.

+2

Zgodnie z opisem zmiany w GitHub pod adresem https://github.com/scala/scala/commit/e1780e9686914d835b295e125511368eeb1d0733#L0L350, zamiast A <% B', ponieważ mają one ta sama semantyka. –

-1

Prawidłowe wykorzystanie wydaje się być

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

chodzi o przeciążonych wartości scala nie decyduje się rozwiązać dwuznaczność; w takim przypadku musisz zdecydować.

  • można spróbować debugowania: -Xprint:typer

  • lub można zdecydować, że A jest rzeczywiście Int przez albo za pomocą class Container[A](value: A) { def addIt = 123 + value.asInstanceOf[Int] } lub już zasugerował class Container[A](value: A) { def addIt(implicit evidence: A => Int) = 123 + value }. Są one równoważne. Ale tutaj mówisz, że A jest typu Int; w przeciwieństwie do A można zobaczyć jako Int, co robi <%.

Ta druga opcja nie jest trywialna.Rozważmy następujący

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 

Wyraźnie "love" nie jest typem Int ponieważ jest String, ale jest to całkowicie w porządku w tym kontekście: dlatego należy być ostrożnym przy użyciu A => Int.

+0

Fragment na górze to zdecydowanie nie jest prawidłowe użycie! Parametr typu "A" w metodzie "addIt" zacienia parametr "A" na klasie, więc nie dodaje nic do tej sytuacji. – Impredicative

+0

Twój drugi przykład działa tylko z powodu globalnego niejawnego 'any2stringAdd', który pozwala konwertować dowolny typ na ciąg w celu jego połączenia - co jest całkowicie przypadkowe dla tego pytania. Ponadto nie jest prawdą, że '{def addIt = 123 + value.asInstanceOf [Int]}' i '{def addIt (domniemany dowód: A => Int) = 123 + wartość}' są równoważne. Jednym z nich jest niebezpieczna obsada, która wysadzi się w czasie kompilacji dla czegoś, czego nie jest podtypem Int. Drugi jest bezpieczny dla typu, polegający na niejawnej konwersji w zakresie. – Impredicative

+0

Niestety, wysadzić w czasie wykonywania, a nie czas kompilacji. – Impredicative

Powiązane problemy