2012-10-27 32 views
6

Tại sao mã này không hoạt động:mất tích kiểu tham số lỗi bằng cách gọi toSet

scala> List('a', 'b', 'c').toSet.subsets.foreach(e => println(e)) 

<console>:8: error: missing parameter type 
       List('a', 'b', 'c').toSet.subsets.foreach(e => println(e)) 
                 ^

Nhưng khi tôi chia nó sau đó nó hoạt động tốt:

scala> val itr=List('a', 'b', 'c').toSet.subsets 
itr: Iterator[scala.collection.immutable.Set[Char]] = non-empty iterator 

scala> itr.foreach(e => println(e)) 
Set() 
Set(a) 
Set(b) 
Set(c) 
Set(a, b) 
Set(a, c) 
Set(b, c) 
Set(a, b, c) 

Và mã này là OK cũng như:

Set('a', 'b', 'c').subsets.foreach(e => println(e)) 
+1

có thể trùng lặp của [Loại suy luận về Đặt lỗi?] (Http://stackoverflow.com/questions/5544536/type-inference-on-set-failing) – sschaef

Trả lời

6

Thứ nhất, có một phiên bản đơn giản của các mã có cùng một vấn đề:

0.123.
List('a', 'b', 'c').toSet.foreach(e => println(e)) 

này không hoạt động hoặc

List('a', 'b', 'c').toBuffer.foreach(e => println(e)) 

Tuy nhiên, những công việc tốt:

List('a', 'b', 'c').toList.foreach(e => println(e)) 
List('a', 'b', 'c').toSeq.foreach(e => println(e)) 
List('a', 'b', 'c').toArray.foreach(e => println(e)) 

Nếu bạn đi tham quan một cái nhìn tại các List class documentation bạn sẽ thấy rằng các phương pháp làm việc trả về một số kiểu được tham số hóa với A, trong khi các phương thức không hoạt động các kiểu trả về được tham số hóa với B >: A. Vấn đề là trình biên dịch Scala không thể tìm ra được B nào để sử dụng! Điều đó có nghĩa nó sẽ làm việc nếu bạn nói với nó loại:

List('a', 'b', 'c').toSet[Char].foreach(e => println(e)) 

Bây giờ như đối với tại saotoSettoBuffer có chữ ký, tôi không có ý tưởng ...

Cuối cùng, không chắc chắn nếu điều này là hữu ích, nhưng công trình này quá:

// I think this works because println can take type Any 
List('a', 'b', 'c').toSet.foreach(println) 

cập nhật: Sau khi chọc xung quanh các tài liệu một chút nữa tôi nhận thấy rằng phương pháp này hoạt động trên tất cả các loại s với thông số loại covariant, nhưng thông số loại bất biến có loại B >: A trong loại trả về. Thật thú vị, mặc dù Array là bất biến trong Scala họ cung cấp hai phiên bản của phương pháp (một với A và một với B >: A), đó là lý do tại sao nó không có lỗi đó.

Tôi cũng chưa bao giờ thực sự trả lời lý do phá vỡ biểu thức thành hai dòng hoạt động. Khi bạn chỉ cần tự gọi toSet, trình biên dịch sẽ tự động suy ra AB trong loại cho kết quả Set[B], trừ khi bạn cung cấp cho nó một loại cụ thể để chọn. Đây chỉ là cách thuật toán suy luận kiểu hoạt động. Tuy nhiên, khi bạn ném loại khác loại không xác định vào kết hợp (nghĩa là loại e trong lambda của bạn) thì thuật toán suy luận và chết - nó không thể xử lý một số chưa biết B >: A và loại không xác định là e.

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