0
votes

I have an abstract class with a method that receives an HList's as parameter (A). However in the subclasses I'd like to restrict the exact types of this HList (B)

The code below doesn't work (it doesn't see (Int :: String :: HNil) as subclass of HList. But how can achieve a similar effect?

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)
1

1 Answers

3
votes

Even without HLists, this is not something you can do in Scala as-is. Imagine trying to do something simpler

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 = //...
}

This doesn't work because B.test does not have the same signature as A.test. One has a type parameter while the other does not. Inheritance requires that a B should be able to act as an A, but that clearly cannot happen here.

Instead, you could move the type parameter to the class itself:

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

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

This should also work fine when using HLists.