2012-10-24 26 views
7

Tôi là loại mới đối với Scala và tôi có một câu hỏi về hệ thống kiểu.Trình kiểm tra loại Scala biết cách ngăn chặn gọi flatten trên Danh sách đã phẳng

Phương pháp flatten hoạt động trên các bộ sưu tập lồng nhau, vì vậy nếu tôi có Danh sách các danh sách, nó sẽ làm phẳng nó vào Danh sách. Nhưng nó không có ý nghĩa để gọi flatten trên một bộ sưu tập đã được bằng phẳng. Và chắc chắn rằng trình kiểm tra loại Scala sẽ gắn cờ đó là một lỗi.

List(List(1,2,3),List(4,5,6)).flatten // produces List(1,2,3,4,5,6) 
List(1,2,3,4).flatten // type error 

Tôi hiểu rằng điều này bằng cách nào đó dựa vào tham số ẩn để làm phẳng. Nhưng tôi không biết giá trị tiềm ẩn đến từ đâu và nó được sử dụng như thế nào để khẳng định kiểu của đối tượng flatten được gọi. Ngoài ra, tại sao không tham số ngầm hiển thị trong scaladocs cho List.flatten?

Trả lời

4

Để hiểu cách làm việc này, chúng ta cần phải có một cái nhìn tại các loại chữ ký của flatten:

def flatten[B](implicit asTraversable: (A) ⇒ GenTraversableOnce[B]): List[B] 

A là loại yếu tố của danh sách và B là loại các yếu tố của từng yếu tố. Để làm phẳng, phải có chuyển đổi ngầm từ kiểu phần tử thành GenTraversableOnce[B]. Đó chỉ là trường hợp cho các bộ sưu tập hoặc nếu bạn thực hiện chuyển đổi tiềm ẩn của riêng bạn. Ví dụ: bạn có thể xác định một cặp cho các cặp:

implicit def pairToList[A](p:(A,A)) = List(p._1, p._2) 

List(1->2,2->3).flatten //compiles! List(1,2,2,3) 
+0

Chuyển đổi không cần phải ngầm định, nó cũng hoạt động: Danh sách (1-> 2,3-> 4) .flatten (p => Danh sách (p._1, p._2)) –

+1

Chắc chắn, mọi thông số ngầm định cũng có thể được chuyển một cách rõ ràng. –

1

Bí quyết là một nhân chứng ngầm để đảm bảo rằng các yếu tố trong danh sách có thể đi ngang. Dưới đây là (hơi đơn giản) chữ ký của flatten lấy từ GenericTraversableTemplate:

def flatten[B](implicit asTraversable: A => TraversableOnce[B]) 
       : GenTraversable[B] = 

Trong trường hợp của bạn, trước sự chứng kiến ​​không thể được tìm thấy cho các yếu tố của loại Int, và do đó gọi của flatten bị từ chối bởi trình biên dịch.


Nếu bạn muốn tạo ra ví dụ của bạn biên dịch, bạn có thể sử dụng định nghĩa ngầm sau:

implicit def singleToList[A](a: A) = List(a) 

(Là một phụ lưu ý: Tôi muốn xem xét như một tiềm ẩn như khá nguy hiểm, vì nó Khả năng ứng dụng là rất chung chung, điều này có thể dẫn đến những bất ngờ khó chịu vì trình biên dịch có thể tiêm các lời mời ở những nơi khác nhau mà không cần bạn biết.)

+0

Có nơi nào đó trong thư viện chuẩn, nơi ẩn chứa được khai báo để chuyển đổi từ Danh sách thành TraversableOnce không? Hay nó chỉ tồn tại tự động vì List là một kiểu con của TraversableOnce? –

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