Ваш второй EncodePoly
близок, но компилятор недостаточно умен, чтобы сделать вывод, что K
должно быть Int
, а затем C
должно быть синглтонного типа. Вы можете вывести вывод типа, кодируя отношение подтипа, используя <:<
вместо <:
:
trait Common[K] {
def name: String
def encode(k: K): String = name + k.toString
}
object A extends Common[Int] {
override def name: String = "a"
}
object B extends Common[Int] {
override def name: String = "b"
}
object C extends Common[Int] {
override def name: String = "c"
}
import shapeless.{ ::, HNil, Poly1 }
object EncodePoly extends Poly1 {
implicit def indCase[K, C](implicit ev: C <:< Common[K]): Case.Aux[C, K => String] = at[C] {
common => k => common.encode(k)
}
}
А потом:
scala> val hl = A :: B :: C :: HNil
hl: A.type :: B.type :: C.type :: shapeless.HNil = A$@3f044518 :: B$@282b7aad :: C$@7c130749 :: HNil
scala> val result: List[Int => String] = hl.map(EncodePoly).toList
result: List[Int => String] = List(EncodePoly$$$Lambda$5555/1493211716@7c987ea3, EncodePoly$$$Lambda$5555/1493211716@10be689, EncodePoly$$$Lambda$5555/1493211716@5dd3c2f2)
Если вы можете исправить K
в Int
в своем определении EncodePoly
, это также сработает.