Theo tôi, hai ví dụ đơn giản nhất sau khi Function
được đặt hàng và bình đẳng. Tuy nhiên, thứ nhất không phải là biến thể trong thư viện chuẩn của Scala, và thứ hai thậm chí không tồn tại trong nó. Vì vậy, tôi sẽ sử dụng tương đương Scalaz: Order và Equal.
Tiếp theo, tôi cần một số cấu trúc phân cấp lớp, tốt nhất là một cấu trúc quen thuộc và dĩ nhiên, cả hai khái niệm trên đều phải có ý nghĩa đối với nó. Nếu Scala có một lớp bậc trên Number
của tất cả các loại số, điều đó sẽ hoàn hảo. Thật không may, nó không có điều như vậy.
Vì vậy, tôi sẽ cố gắng tạo các ví dụ với các bộ sưu tập. Để đơn giản, hãy xem xét Seq[Int]
và List[Int]
. Phải rõ ràng rằng List[Int]
là một loại phụ của Seq[Int]
, tức là, List[Int] <: Seq[Int]
.
Vì vậy, chúng tôi có thể làm gì với ứng dụng này? Đầu tiên, chúng ta hãy viết một cái gì đó so sánh hai danh sách:
def smaller(a: List[Int], b: List[Int])(implicit ord: Order[List[Int]]) =
if (ord.order(a,b) == LT) a else b
Bây giờ tôi sẽ viết một ngầm Order
cho Seq[Int]
:
implicit val seqOrder = new Order[Seq[Int]] {
def order(a: Seq[Int], b: Seq[Int]) =
if (a.size < b.size) LT
else if (b.size < a.size) GT
else EQ
}
Với những định nghĩa này, bây giờ tôi có thể làm một cái gì đó như thế này:
scala> smaller(List(1), List(1, 2, 3))
res0: List[Int] = List(1)
Lưu ý rằng tôi yêu cầu Order[List[Int]]
, nhưng tôi đang chuyển một số Order[Seq[Int]]
. Điều này có nghĩa là Order[Seq[Int]] <: Order[List[Int]]
. Cho rằng Seq[Int] >: List[Int]
, điều này chỉ có thể vì contra-variance.
Câu hỏi tiếp theo là: nó có ý nghĩa gì không?
Hãy xem xét lại smaller
. Tôi muốn so sánh hai danh sách các số nguyên. Đương nhiên, bất cứ điều gì so sánh hai danh sách là chấp nhận được, nhưng logic của cái gì đó so sánh hai Seq[Int]
là chấp nhận được?
Lưu ý trong định nghĩa của seqOrder
cách những thứ được so sánh sẽ trở thành thông số cho nó. Rõ ràng, một List[Int]
có thể là một tham số cho một cái gì đó mong đợi một Seq[Int]
. Từ đó sau đó một cái gì đó mà một cái gì đó so sánh Seq[Int]
là chấp nhận được ở vị trí của một cái gì đó so sánh List[Int]
: cả hai đều có thể được sử dụng với các thông số tương tự.
Điều gì ngược lại? Giả sử tôi có phương pháp chỉ so sánh ::
(khuyết điểm của danh sách), cùng với Nil
, là loại phụ của List
. Tôi rõ ràng không thể sử dụng điều này, bởi vì smaller
cũng có thể nhận được Nil
để so sánh. Không thể sử dụng Order[::[Int]]
thay vì Order[List[Int]]
.
Hãy tiến tới bình đẳng, và viết một phương pháp cho nó:
def equalLists(a: List[Int], b: List[Int])(implicit eq: Equal[List[Int]]) = eq.equal(a, b)
Vì Order
kéo dài Equal
, tôi có thể sử dụng nó với cùng ngầm trên:
scala> equalLists(List(4, 5, 6), List(1, 2, 3)) // we are comparing lengths!
res3: Boolean = true
Logic ở đây là cùng một. Bất cứ điều gì có thể cho biết hai Seq[Int]
là cùng một có thể, rõ ràng, cũng cho biết liệu hai List[Int]
là như nhau. Từ đó, nó theo sau là Equal[Seq[Int]] <: Equal[List[Int]]
, điều này đúng bởi vì Equal
là một biến thể.
Xem câu trả lời của Daniel Spiewak cho http: // stackoverflow.com/questions/663254/scala-hiệp phương sai-contravariance-câu hỏi – sourcedelica
... bởi vì không ai sử dụng các chức năng trong thế giới thực? =) –