Переопределение параметра Shapeless HList

У меня есть абстрактный класс с методом, который получает HList в качестве параметра (A). Однако в подклассах я хотел бы ограничить точные типы этого HList (B)

Приведенный ниже код не работает (он не рассматривает (Int :: String :: HNil) как подкласс HList. Но как добиться аналогичного эффекта?

import shapeless.{::, HList, HNil}
import shapeless.syntax.std.tuple._

abstract class A{
  def test[H <: HList](h: H): String
}


class B extends A {
  override def test(h: (Int :: String :: HNil)): String = {
    val a = h(0)
    val b = h(1)
    s"$a -- $b"
  }
}


new B().test(25  :: "testje" ::  HNil)

person Tom Lous    schedule 03.10.2017    source источник


Ответы (1)


Даже без HLists это не то, что вы можете сделать в Scala как есть. Представьте, что вы пытаетесь сделать что-то попроще

trait Foo
trait Bar extends Foo

abstract class A {
  def test[T <: Foo](t: T): String
}

class B extends A {
  override def test(b: Bar): String = //...
}

Это не работает, потому что B.test не имеет той же подписи, что и A.test. У одного есть параметр типа, а у другого - нет. Наследование требует, чтобы B мог действовать как A, но здесь этого явно не может быть.

Вместо этого вы можете переместить параметр типа в сам класс:

abstract class A[T <: Foo] {
  def test(t: T): String
}

class B extends A[Bar] {
  override def test(b: Bar): String = //...
}

Это также должно работать нормально при использовании HLists.

person Dan Simon    schedule 03.10.2017