2011-07-31 43 views
13

xem xét mã Scala sau:Tại sao Scala không suy ra đầy đủ các tham số kiểu khi các tham số kiểu được lồng nhau?

abstract class A 
abstract class B[T <: A] 
class ConcreteA extends A 
class ConcreteB extends B[ConcreteA] 

class Example[U <: B[T], T <: A](resolver: U) 
object Test { 
    new Example(new ConcreteB) 
} 

Dòng cuối cùng new Example(new ConcreteB) thất bại trong việc biên dịch với các lỗi sau:

error: inferred type arguments [ConcreteB,Nothing] do not conform to class Example's type parameter bounds [U <: B[T],T <: A]

Nhưng ConcreteB có tất cả các dữ liệu cần thiết để giải quyết cả U T. Tôi đang thiếu gì ở đây?

+0

bản sao có thể có của [Loại infered to Nothing in Scala] (http://stackoverflow.com/questions/6888136/type-infered-to-nothing-in-scala) –

+1

Nó tương tự, nhưng câu trả lời được chấp nhận cho rằng câu hỏi không áp dụng trong trường hợp này. –

Trả lời

10

Kipton đã gần gũi với giải pháp cao cấp của mình. Thật không may, ông vấp phải những gì dường như là một lỗi trong Scala < 2.9.1.RC1. Các công trình sau đây như mong đợi với 2.9.1.RC1 và thân cây,

Welcome to Scala version 2.9.1.RC1 (Java HotSpot(TM) Server VM, Java 1.7.0). 
Type in expressions to have them evaluated. 
Type :help for more information. 

scala> abstract class A 
defined class A 

scala> abstract class B[T <: A] 
defined class B 

scala> class ConcreteA extends A 
defined class ConcreteA 

scala> class ConcreteB[T <: A] extends B[T] 
defined class ConcreteB 

scala> class Example[T <: A, U[X <: A] <: B[X]](resolver: U[T]) 
defined class Example 

scala> new Example(new ConcreteB[ConcreteA]) 
res0: Example[ConcreteA,ConcreteB] = [email protected] 
+0

Nó gần, nhưng sau đó ConcreteB không thực sự cụ thể. Điều này làm việc cho bạn mà không cần phải tham số rõ ràng ConcreteB? –

+0

Tôi không thể suy luận để làm việc mà không có tham số rõ ràng của 'ConcreteB' (nhưng cách tiếp cận thành viên kiểu tôi đã đề cập lúc đầu hoạt động tốt). –

+0

Cảm ơn, tôi đoán điều này là gần như nó được vào thời điểm này. –

10

(Xem thêm hai câu hỏi liên quan: Scala fails to infer the right type argumentsType infered to Nothing in Scala)

Nó trông giống như một giới hạn của suy luận kiểu Scala, mà là cố ý không spec'ed. Như công việc xung quanh, bạn có thể nhận được kết luận bằng cách làm cho T một loại viên của B chứ không phải là tham số,

abstract class A 
abstract class B { type T <: A } 
class ConcreteA extends A 
class ConcreteB extends B { type T = ConcreteA } 
class Example[U <: B](resolver: U) 
object Test { 
    new Example(new ConcreteB) 
} 

Khi sử dụng các thành viên loại, nó là hữu ích để biết rằng họ có thể nổi lên như các tham số kiểu sử dụng tinh tế, như trong câu trả lời của Miles Sabin cho: Why is this cyclic reference with a type projection illegal?

Trong câu trả lời của Jean-Philippe Pellet với a related question, suy luận kiểu được hỗ trợ bằng cách làm cho thông số loại cao hơn. Nếu bạn giới thiệu một số loại phụ trong ConcreteB, sau đó gõ suy luận có thể làm việc,

abstract class A 
abstract class B[T <: A] 
class ConcreteA extends A 
class ConcreteB[T <: A] extends B[T] 
class Example[T <: A, U[T0 <: A] <: B[T0]](resolver: U[T]) 
object Test { 
    new Example(new ConcreteB[ConcreteA]) 
} 

Scala 2.9 đưa ra thông điệp lỗi bí ẩn bên dưới, nhưng Miles Sabin chỉ ra nó là một lỗi sẽ được cố định cho 2,9. 1

<console>:15: error: kinds of the type arguments (ConcreteA,ConcreteB[T0]) do not conform to the expected kinds of the type parameters (type T,type U) in class Example. 
ConcreteB[T0]'s type parameters do not match type U's expected parameters: class ConcreteB has one type parameter, but type U has one 
     new Example(new ConcreteB[ConcreteA]) 
      ^
+1

Xem phần thảo luận tiếp theo về câu trả lời của Miles dưới đây. –

+0

Câu trả lời của Miles đã ở trên vì nó đã trở thành câu trả lời được chấp nhận. – ArtB

2

Tôi đã sáng tác a document of type inference workarounds trên GitHub cho việc học tập của riêng tôi.

Một vài quy tắc đơn giản mà tôi thấy hữu ích là:

  • Loại thông số của các tham số kiểu không thể được suy ra: Scala suy luận kiểu chỉ nhìn thấy loại được xác định trong danh sách tham số (không được lẫn lộn với danh sách tham số loại).

  • thông số trước không được sử dụng để suy ra các thông số trong tương lai: Loại thông tin duy nhất chảy qua tham số danh sách, không thông số.


Tuy nhiên, trong ví dụ cụ thể này thành viên loại là con đường phía trước (nhờ @Kipton Barros!)

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