2010-03-02 35 views
5

Các tài liệu scala nói rằng Enumeration.Val có trật tự, tuy nhiên tôi nhận được hành vi không phù hợp khi khi tôi cố gắng để thực thi hạn chế loại trên các giá trị liệt kê yêu cầu họ hỗ trợ đặt hàng:Giá trị liệt kê Scala không được đặt hàng?

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

Trong hai báo cáo cuối cùng, là người đầu tiên hoạt động và hiển thị rằng các giá trị liệt kê có một thứ tự được xác định. Trường hợp thứ hai đưa ra một lỗi:

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

Làm cách nào để nhận được thông tin này và sử dụng các giá trị liệt kê theo các phương pháp chung mà yêu cầu đặt hàng?

Trả lời

8

Vấn đề ở đây là Value thực hiện Ordered[Enumeration#Value], thay vì Ordered[Dogs.Value]. Tôi không biết lý do cho điều này, nó không thể làm điều đó theo cách khác.

này là đủ đối với trường hợp đơn giản trực tiếp so sánh hai giá trị - nó chỉ là một phương pháp gọi bình thường:

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

Tuy nhiên, các loại tham số A trong Ordered là bất biến, vì vậy khi bạn bạn yêu cầu loại thông số có thể xem là Ordered[A], không đủ để sử dụng Dogs.Value <: Ordered[Enumeration#Value]. Nếu A là đối nghịch, điều này sẽ được cho phép, nhưng nó cũng gây ra các vấn đề khác với suy luận kiểu.

Bạn có thể làm việc xung quanh vấn đề bằng cách tĩnh gõ danh sách với 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) 

Hoặc, bằng cách thông qua một cách rõ ràng tham số kiểu để doSomething:

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

Hoặc, tốt hơn chưa, nới lỏng các các yêu cầu về các thông số kiểu, về cơ bản xử lý Ordered như là một biến thể trong trường hợp này.

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) 

Tại sao tính năng này hoạt động?

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

Cảm ơn @retronym, ví dụ cuối cùng này đã giải quyết được vấn đề của tôi, mặc dù tâm trí của tôi đang bị hạn chế về các loại ràng buộc yếu hơn! Nó bây giờ yêu cầu bất kỳ loại A, cung cấp A có thể được coi là (tức là, hoặc có thể được chuyển đổi sang) một cái gì đó Đặt hàng bằng một tổng quát của A. Đó có phải là về đúng không? –

Các vấn đề liên quan