Giả sử chúng ta có các lớp học và một số giá trị (trong Scala) sau:Bản đồ trên HList không thành công với tuýp phụ của loại chung trong Scala & hình thù
class A[T](val x: T)
class B[T](x: T, val y: T) extends A[T](x)
val x1 = new A("test")
val x2 = new B(1,2)
val x3 = new B("foo","bar")
val x4 = new A(1)
Hơn nữa, chúng tôi xác định giá trị hàm đa hình sau (sử dụng hình thù) :
object f extends (A ~> Option) {
def apply[T](s: A[T]) = Some(s.x)
}
Bây giờ chúng ta có thể gọi:
f(x1); f(x2); f(x3); f(x4)
Mà tất cả thành công (và nên IMHO). Tuy nhiên:
val list = x1 :: x2 :: x3 :: x4 :: HNil
list.map(f)
// could not find implicit value for parameter mapper:
// shapeless.Mapper[f.type,shapeless.::[A[String],shapeless.::[
// B[Int],shapeless.::[B[String],shapeless.::[A[Int],shapeless.HNil]]]]]
đâu tôi đã mong đợi:
Some("test") :: Some(1) :: Some("foo") :: Some(1) :: HNil
Lưu ý rằng công trình này:
val list2 = x1 :: x4 :: HNil // only instances of A
list2.map(f)
CẬP NHẬT
Dường như nếu chúng ta xác định từng trường hợp riêng biệt, được rồi:
object f extends Poly1 {
implicit def caseA[T] = at[A[T]]{s => Some(s.x)}
implicit def caseB[T] = at[B[T]]{s => Some(s.x)}
}
Tuy nhiên, cố gắng thể hiện điều này một chút thông minh hơn, không làm việc (thậm chí không cho các ứng dụng đơn giản):
object f extends Poly1 {
implicit def caseA[T, S <: A[T]] = at[S]{s => Some(s.x)}
}
Tôi không thể cung cấp câu trả lời đầy đủ vào lúc này, nhưng cách khắc phục đơn giản nhất là sử dụng chế độ xem được gắn cho 'S' trong phiên bản' f' cuối cùng của bạn (nghĩa là 'S <% A [T]') . Hoặc ít nhất điều đó sẽ hoạt động và không yêu cầu bạn thêm các trường hợp cho mỗi loại phụ của 'A'. –
@TravisBrown Cảm ơn rất nhiều vì câu trả lời nhanh. Điều đó thực sự có vẻ hiệu quả. Tôi thực sự mong muốn biết tại sao, nếu bạn có một câu trả lời hoặc con trỏ đơn giản. Nếu không -> mã đào – gzm0