Hãy tưởng tượng một kiểu chữ để nhận phần tử cuối cùng của bất kỳ bộ dữ liệu nào.
trait Last[A] {
type B
def last(a: A): B
}
object Last {
type Aux[A,B0] = Last[A] { type B = B0 }
implicit def tuple1Last[A]: Aux[Tuple1[A],A] = new Last[Tuple1[A]] {
type B = A
def last(a: Tuple1[A]) = a._1
}
implicit def tuple2Last[A,C]: Aux[(A,C),C] = new Last[(A,C)] {
type B = C
def last(a: (A,C)) = a._2
}
...
}
Loại B
luôn phụ thuộc vào loại A
, đó là lý do tại sao A
là một loại đầu vào của typeclass và B
là một loại sản lượng.
Bây giờ nếu bạn muốn một hàm có thể sắp xếp bất kỳ danh sách bộ dữ liệu nào dựa trên phần tử cuối cùng bạn cần truy cập vào loại B
trong cùng một danh sách đối số. Đó là lý do chính, trong trạng thái hiện tại của Scala, tại sao bạn cần mẫu Aux
: hiện tại không thể tham chiếu đến loại last.B
trong cùng một danh sách tham số như trong đó last
được định nghĩa, cũng không thể có nhiều danh sách tham số ngầm .
def sort[A,B](l: List[A])(implicit last: Last.Aux[A,B], ord: Ordering[B]) = ???
Tất nhiên bạn luôn có thể viết Last[A] { type B = B0 }
ra đầy đủ, nhưng rõ ràng rằng trở nên rất không thực tế rất nhanh chóng (tưởng tượng thêm một vài thông số ngầm hơn với các loại phụ thuộc, một cái gì đó là rất phổ biến với hình thù); đó là nơi mà bí danh loại Aux
có sẵn.
Nguồn
2017-05-10 19:20:11
'loại B' hoạt động giống như A, chỉ tên được đặt tên và có thể được tham chiếu, trái với A. – pedrofurla