2010-03-02 22 views
5

Ölçekli dokümanlar, Enumeration.Val öğesinin sipariş edildiğini söylüyor, ancak sıralamayı desteklemelerini gerektiren numaralandırmalarla ilgili sıralama kısıtlamalarını zorlamaya çalıştığımda tutarsız davranış alıyorum:Scala Numaralandırma değerleri sipariş edilmiyor?

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 =(

Son iki ifadeden ilk eserler ve Numaralandırma değerlerinin tanımlanmış bir siparişi olduğunu gösterir. İkincisi bir hata verir:

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

Bunu nasıl elde edebilirim ve sipariş vermeyi gerektiren jenerik yöntemlerde numaralandırma değerlerini nasıl kullanırım?

cevap

8

Sorun, Ordered[Dogs.Value] yerine Value uygulayıcıları Ordered[Enumeration#Value] uygulanmaktadır. Bunun mantığını bilmiyorum, bunu başka şekilde yapmak mümkün değil.

Bu doğrudan iki değeri karşılaştırarak basit durum için yeterlidir - onun sadece normal bir yöntem çağrısı: Eğer türü için sorduğunuzda

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

Ancak türü parametresi AOrdered kadar, değişmez olduğu Ordered[A] olarak görüntülenebilen param, Dogs.Value <: Ordered[Enumeration#Value]'u kullanmak için yeterli değildir. Eğer A kontr-varyant ise bu izin verilebilir, fakat aynı zamanda tür çıkarımında başka problemlere de neden olur.

Sen statik Enumeration#Value listeyi yazarak soruna olabilir: Açıkça doSomething için türü parametresi geçirerek

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) 

Veya ölçütü:

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

Veya daha iyisi, gevşeme Bu durumda, esas olarak Ordered 'un kontravaryant olarak ele alındığı tip parametrelerine olan gereksinimler.

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) 

Neden bu işe yarıyor?

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

Teşekkürler @retronym, bu son örnek sorunumu çözdü, ancak zihnim zayıf tip kısıtlamalardan bükülüyor olsa da! Şu anda A, A'nın genelleştirilmesiyle sipariş edilen bir şey olarak kabul edilebilir (yani, ya da dönüştürülebilen) bir A tipi gerektirir. –