2010-03-02 11 views
5

Docs scala że Enumeration.Val jest uporządkowane, jednak otrzymuję niespójne zachowanie podczas gdy próbuję wymusić ograniczenia typu na wartości wyliczenia wymagając od nich wsparcie zamawiającego:Wartości wyliczenia Scala nie zostały zamówione?

object Dogs extends Enumeration { 
    val Sam, Tom, Rover = Value 
} 

def doSomething[A <% Ordered[A]](a : List[A]) : Unit = { 
    println(a.sortWith(_ < _)) 
} 

import Dogs._ 

val xs = List(Rover, Tom, Sam, Sam, Rover) 

println(xs.sortWith(_ < _)) // works! 
doSomething(xs)    // fails =(

ostatnich dwóch sprawozdań, pierwszy działa i pokazuje, że wartości wyliczeniowe mają zdefiniowane porządkowanie. Drugi daje błąd:

could not find implicit value for evidence parameter of type (this.Dogs.Value) => Ordered[this.Dogs.Value] 

Jak obejść ten problem i użyć wartości wyliczeniowych w ogólnych metodach wymagających zamawiania?

Odpowiedz

8

Problem polega na tym, że realizatorzy Ordered[Enumeration#Value] zamiast Ordered[Dogs.Value]. Nie znam racji na to, nie można tego zrobić inaczej.

Jest to wystarczające dla prostego przypadku bezpośredniego porównywania dwóch wartości - jej tylko normalną metodę połączenia:

scala> (Rover: Ordered[Enumeration#Value]).<(Sam) 
res44: Boolean = false 

Jednak parametr typu A w Ordered jest niezmienna, więc gdy pytasz o rodzaju Parametr, który można wyświetlić jako Ordered[A], nie wystarczy użyć Dogs.Value <: Ordered[Enumeration#Value]. Jeśli A byłby wariant przeciwny, byłoby to dozwolone, ale powoduje także inne problemy z wnioskiem o typ.

Można obejść ten problem przez statycznie wpisując listę z Enumeration#Value:

scala> val xs = List[Enumeration#Value](Rover, Tom, Sam, Sam, Rover) 
xs: List[Enumeration#Value] = List(Rover, Tom, Sam, Sam, Rover) 

scala> doSomething(xs)     
List(Sam, Sam, Tom, Rover, Rover) 

Albo jawnie przekazując parametr typu do doSomething:

scala> doSomething[Enumeration#Value](List(Rover, Sam))       
List(Sam, Rover) 

Albo, jeszcze lepiej, poluzowanie wymagania dotyczące parametrów typu, zasadniczo traktując Ordered jako sprzeczne z powyższymi warunkami.

scala> def doSomething[A <% Ordered[_ >: A]](xs : List[A]) = xs sortWith (_ < _) 
doSomething: [A](xs: List[A])(implicit evidence$1: (A) => Ordered[_ >: A])List[A] 

scala> doSomething(List(Rover, Sam))            
res47: List[Dogs.Value] = List(Sam, Rover) 

Dlaczego to działa?

scala> Rover: Ordered[_ <: Enumeration#Value] 
res52: scala.math.Ordered[_ <: Enumeration#Value] = Rover 
+0

Dzięki @retronym, ten ostatni przykład rozwiązał mój problem, chociaż mój umysł zgiął się od słabszych ograniczeń typu! Wymaga on teraz dowolnego typu A, pod warunkiem, że A może być traktowany jako (to znaczy jest, lub może zostać przekonwertowany) na coś Zlecony przez uogólnienie A. Czy to prawda? –

Powiązane problemy