2013-06-04 28 views
5

tôi đang cố gắng để có được một sự hiểu biết tốt hơn về các hành vi sau đây:Scala loại vọt & sai

scala> class C[-A, +B <: A] 
<console>:7: error: contravariant type A occurs in covariant position 
        in type >: Nothing <: A of type B 
     class C[-A, +B <: A] 
        ^

Tuy nhiên các công việc sau:

scala> class C[-A, +B <% A] 
defined class C 

tôi có thể thấy rằng có thể có vấn đề từ phương sai của các biến giới hạn và giới hạn được đối lập, mặc dù tôi không rõ ràng về vấn đề cụ thể là gì. Tôi thậm chí còn ít rõ ràng hơn về lý do tại sao việc thay đổi loại bị ràng buộc thành một khung nhìn bị ràng buộc làm cho mọi việc trở nên ổn thỏa. Trong trường hợp không có chuyển đổi tiềm ẩn áp dụng, tôi mong đợi hai định nghĩa sẽ có tác động tương tự. Nếu bất cứ điều gì tôi mong đợi một quan điểm ràng buộc để cung cấp nhiều cơ hội cho sự nghịch ngợm.

Đối với một chút của nền tôi xác định lớp mà nằm trong một số cách như chức năng, và tôi muốn làm một cái gì đó giống như

CompositeFunc[-A, +B <: C, -C, +D] (f1 : BaseFunc[A, B], f2 : BaseFunc[C, D]) 
    extends BaseFunc[A, D] 

Có thể cho rằng

CompositeFunc[-A, +B <% C, -C, +D] (f1 : BaseFunc[A, B], f2 : BaseFunc[C, D]) 
    extends BaseFunc[A, D] 

thực sự là một lợi thế, nhưng tôi sẽ vẫn muốn hiểu rõ hơn những gì đang xảy ra ở đây.

+0

hấp dẫn ... Tôi đã dành 1 giờ tìm kiếm một ví dụ trong đó loại phá vỡ an toàn với các loại ràng buộc. Không tìm thấy: ( – gzm0

+0

Ngoài ra, nếu có một ví dụ không được gắn kết với loại bị ràng buộc, thật khó để thấy cách thay thế trong một khung nhìn bị ràng buộc sẽ sửa chữa nó. –

+0

Vâng, tôi đồng ý một chút. luôn luôn chuyển đổi theo các loại lớp đã được tạo ra với, trong khi điều này không nhất thiết phải là trường hợp với các loại ràng buộc. (nói trực giác của tôi ít nhất ...) – gzm0

Trả lời

4

Đầu tiên là điều dễ dàng:

class C[-A, +B <% A] 

này tương đương với

class C[-A, +B](implicit view: B => A) 

Kể từ view không công khai trở lại, nó không phải là ở một vị trí mà sẽ hạn chế phương sai của A hoặc B. Ví dụ.

class C[-A, +B](val view: B => A) // error: B in contravariant position in view 

Nói cách khác, C[-A, +B <% A] là không khác gì so C[-A, +B] về những hạn chế, lập luận quan điểm không thay đổi bất cứ điều gì.


Trường hợp ràng buộc trên C[-A, +B <: A] Tôi không chắc chắn. Đặc tả Ngôn ngữ Scala trong §4.5 tiểu bang

Vị trí phương sai của giới hạn dưới của tham số loại hoặc kiểu nhập ngược lại với vị trí phương sai của khai báo hoặc tham số kiểu.

Phương sai của B dường như không được tham gia, nhưng nói chung là trên ràng buộc phải hiệp biến:

trait C[-A, B <: A] // contravariant type A occurs in covariant position 

này bằng cách nào đó phải xuất trình một vấn đề? Nhưng tôi không thể đưa ra một ví dụ chứng minh rằng việc xây dựng này trở nên bất ổn trong một trường hợp cụ thể ....


Đối với các chức năng sáng tác, tại sao không chỉ

class Composite[-A, B, +C](g: A => B, h: B => C) extends (A => C) { 
    def apply(a: A) = h(g(a)) 
} 

EDIT: Ví dụ:

import collection.LinearSeq 

def compose[A](g: Traversable[A] => IndexedSeq[A], h: Traversable[A] => LinearSeq[A]) = 
    new Composite(g, h) 
+0

Thú vị, cảm ơn.Tôi không nghĩ đến cố gắng 'trait C [-A, B <: A] 'Tôi chỉ nghĩ rằng nó phải là các phương sai ngược lại. –

+0

Vâng, chúng đã soạn, chính xác vì phương sai' Function1' –

+0

lớp 'CompositeFunc [-A, B, + C]' sẽ không cho phép bạn soạn 'f: BaseFunc (Traversable [A], IndexedSeq [A])' với 'g: BaseFunc (Traversable [A], LinearSeq [A])' mặc dù bố cục của chúng có ý nghĩa hoàn hảo trong cả hai đơn đặt hàng. –