Tôi đang cố gắng để xây dựng nhiều sản phẩm chéo của traversables khác nhau (nhưng mỗi đồng nhất) các loại. Kiểu trả về mong muốn là một kiểu đi ngang của một bộ tuple với kiểu phù hợp với các kiểu trong các traversables đầu vào. Ví dụ:Scala: cross (Descartes) sản phẩm với nhiều nguồn và các loại không đồng nhất
List(1, 2, 3) cross Seq("a", "b") cross Set(0.5, 7.3)
Điều này phải cung cấp Traversable[(Int, String, Double)]
với tất cả các kết hợp có thể có từ ba nguồn. Trường hợp kết hợp chỉ có hai nguồn là độc đáo answered here. Ý tưởng đưa ra là:
implicit class Crossable[X](xs: Traversable[X]) {
def cross[A](ys: Traversable[A]) = for { x <- xs; y <- ys } yield (x, y)
}
Các bình luận có đề cập ngắn gọn sự cố nguồn hơn, nhưng tôi đang tìm để tìm một giải pháp mà không phụ thuộc vào một trong hai hình thù hoặc scalaz (mặt khác, tôi don' t tâm có một số boilerplate để quy mô lên đến Tuple22
).
implicit class Crossable[X](xs: Traversable[X]) {
def cross[A](ys: Traversable[A]) = for { x <- xs; y <- ys } yield (x, y)
def cross[A,B](ys: Traversable[(A,B)]) = // ... extend all Tuple2's in ys with x in xs to Tuple3's
def cross[A,B,C](ys: Traversable[(A,B,C)]) = // ...
// ...
}
Điều này rõ ràng không hoạt động do chô bôi loại (và, thật không may, có lẽ sẽ đòi hỏi phải sử dụng dấu ngoặc đơn trong ví dụ trên, bởi vì cross
sẽ là kết hợp đúng: một cái gì đó như sau những gì tôi muốn làm là).
Câu hỏi của tôi là: Có cách nào đó có thể khai thác các tính năng phản chiếu của Scala 2.10 để giải quyết vấn đề không? Nói chung, kết hợp cả hai loại A
và X
với các loại bộ khác nhau (và các tham số kiểu của chúng, có vẻ khó khăn) và hợp nhất chúng thành các bộ dữ liệu lớn hơn sẽ cung cấp giải pháp thỏa mãn luật liên kết, đúng không?
Thật tuyệt vời! Cảm ơn nhiều! Thêm các phiên bản kết hợp phù hợp cũng có vẻ đơn giản với cách tiếp cận này. Tôi nhận thấy bạn đã loại bỏ các lỗi trình biên dịch "không rõ ràng" bằng cách giới thiệu 'crosser2' trong một đặc điểm (nếu không sẽ luôn khớp). Tôi cho rằng phải có một số loại quy tắc ưu tiên phân cấp phụ thuộc vào hệ thống cấp bậc cho implicits? Điều gì vẫn còn khó hiểu với tôi: Tại sao «crosser2',' crosser3', ... thực sự nằm trong phạm vi? Tôi đã hy vọng rằng tôi phải "nhập khẩu Crosser._' để mang lại cho họ trong phạm vi, nhưng điều này dường như không phải là trường hợp. – bluenote10
Trong trường hợp bất kỳ ai khác muốn sử dụng điều này: Tôi vừa viết một trình tạo mã nhỏ (gotta tìm hiểu macro một ngày) và tải lên [Gist] (https://gist.github.com/bluenote10/5465957#file-crossproduct-scala) có chứa tất cả các boilerplate lên đến một mức độ hợp lý cao (bắt đầu với tham số loại 19 tôi đã nhận lỗi trình biên dịch lạ, nhưng 18 nên được quá đủ cho tôi). – bluenote10
Lý do tại sao bạn không cần làm 'import Crosser._', là vì' Crosser' được truyền hoàn toàn trong 'Crossable.cross', và các quy tắc phân giải ngầm nói rằng khi tìm kiếm một giá trị ngầm định của kiểu' T ', trình biên dịch sẽ tự động xem xét các thành viên của đối tượng đồng hành của' T' (nếu có). Xem SLS 7.2 –