While learning shapeless, I wonder, why this doesn't compile:
def someHList[H <: HList]: H = HNil
since the HNil object extends the HNil trait which extends HList?
What is the right way to define a method in a trait which returns some HList, which is only implemented in by the extending class?
I'd like to do something like the following:
trait Parent {
def someHList[H <: HList]: H
}
object Child1 extends Parent {
def someHList[H <: HList] = HNil
}
object Child2 extends Parent {
def someHList[H <: HList] = 1 :: "two" :: HNil
}
Any advice is appreciated. Thanks!
EDIT
To elaborate as I realize what I underspecified in my original question:
1.) It is desirable to not have to specify H
explicitly in each implementing class, but rather let it be inferred (at the call site?).
2.) I'd like to use HNil as a default implementation in the parent trait which can optionally be overridden in subclasses. My example probably should have been:
trait Parent {
def someHList[H <: HList]: H = HNil
}
object Child extends Parent {
override def someHList[H <: HList] = 1 :: "two" :: HNill
}
HNil
object is an HList
. But it is not necessary H
.
definition like
def someHList[H <: HList]: H = HNil
should be read as
for any
type H
, subtype ofHList
there is a way to construct it's member and it will beHNil
which is obviously erroneous
Thing you are trying to do, as I feel, is rephrased version of it to
there is a
type H
, subtype ofHList
and a way to construct it's member
If so you can use type member like this:
import shapeless._
trait Parent {
type H <: HList
def someHList: H
}
object Child1 extends Parent {
type H = HNil
def someHList: H = HNil
}
object Child2 extends Parent {
type H = Int :: String :: HNil
def someHList: H = 1 :: "two" :: HNil
}
You can also refactor it a little bit to make some types infer automatically like
abstract class Parent[H <: HList](val someList: H)
object Child1 extends Parent(HNil: HNil)
object Child2 extends Parent(1 :: "two" :: HNil)
You may note that type for HNil
is set manually, that is because type of object HNil
is a HNil.type
subtype of HNil
, which can lead the compiler wrong way sometimes
If just use HList
as a return type than everything works fine:
trait Parent {
def someHList: HList
}
object Child1 extends Parent {
def someHList = HNil
}
object Child2 extends Parent {
def someHList = 1 :: "two" :: HNil
}
Or for the updated version of the question:
trait Parent {
def someHList: HList = HNil
}
object Child2 extends Parent {
override def someHList = 1 :: "two" :: HNil
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With