że mamy następujące klasy i jakieś wartości (Scala):Mapa na HList nie z podtypów typu rodzajowego w Scala & bezkształtne
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)
Ponadto, możemy zdefiniować następujące wartości funkcji polimorficzny (używając bezkształtne) :
object f extends (A ~> Option) {
def apply[T](s: A[T]) = Some(s.x)
}
teraz możemy nazwać:
f(x1); f(x2); f(x3); f(x4)
którym wszystkie sukces (i powinna IMHO). Jednakże:
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]]]]]
Gdzie Spodziewałem:
Some("test") :: Some(1) :: Some("foo") :: Some(1) :: HNil
Zauważ, że to działa:
val list2 = x1 :: x4 :: HNil // only instances of A
list2.map(f)
UPDATE
Wydaje się, że jeśli mamy określić każdy przypadek oddzielnie, w porządku:
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)}
}
jednak próbuje wyrazić to nieco mądrzejszy, nie działa (nawet do prostych zastosowań):
object f extends Poly1 {
implicit def caseA[T, S <: A[T]] = at[S]{s => Some(s.x)}
}
Nie mogę w tej chwili podać pełnej odpowiedzi, ale najprostszym rozwiązaniem jest użycie widoku związanego dla 'S' w Twojej ostatniej wersji' f' (tj. 'S <% A [T]') . Lub przynajmniej to powinno działać i nie wymaga dodawania przypadków dla każdego podtypu "A". –
@TravisBrown Bardzo dziękuję za szybką odpowiedź. To rzeczywiście wydaje się działać. Naprawdę chciałbym wiedzieć dlaczego, jeśli masz prostą odpowiedź lub wskaźnik. W przeciwnym razie -> kopanie kodu – gzm0