Working with HList
s of options, I am trying to generate an HList
with all elements equal to None
. However, there is a problem with the implicit resolution of the Fill
object.
The natLength
function stems from this SO answer: The length of HList type paremeter in terms of Nat.
type OL = Option[Double] :: Option[Int] :: Option[String] :: HNil
def emptyList[T <: HList: *->*[Option]#λ](length: Nat)(
implicit fill: Fill.Aux[length.N, None.type, T]
): T = {
HList.fill(length)(None)
}
def natLength[T <: HList](implicit length: Length[T]): length.Out = length()
emptyList[OL](natLength[OL])
The above code lets the compiler fail with this error:
could not find implicit value for parameter fill:
shapeless.ops.hlist.Fill[shapeless.Succ[shapeless.Succ[shapeless.Succ[shapeless._0]]],None.type]{type Out = Option[Double] :: Option[Int] :: Option[String] :: shapeless.HNil}
Is what I am trying to achieve possible? Generating an HList
only based on its type's length?
Standard way to debug implicits is to try to resolve them manually (explicitly) and look at compile errors.
emptyList[OL](natLength[OL])(
implicitly[*->*[Option]#λ[Option[Double] :: Option[Int] :: Option[String] :: HNil]],
implicitly[Fill.Aux[_3, None.type, None.type :: None.type :: None.type :: HNil]],
)
produces
Error: type mismatch;
found : shapeless.ops.hlist.Fill[shapeless.nat._3,None.type]{type Out = None.type :: None.type :: None.type :: shapeless.HNil}
(which expands to) shapeless.ops.hlist.Fill[shapeless.Succ[shapeless.Succ[shapeless.Succ[shapeless._0]]],None.type]{type Out = None.type :: None.type :: None.type :: shapeless.HNil}
required: shapeless.ops.hlist.Fill[shapeless.Succ[shapeless.Succ[shapeless.Succ[shapeless._0]]],None.type]{type Out = Option[Double] :: Option[Int] :: Option[String] :: shapeless.HNil}
implicitly[Fill.Aux[_3, None.type, None.type :: None.type :: None.type :: HNil]],
What should be T
in def emptyList[T <: HList: *->*[Option]#λ]...
? Is it Option[Double] :: Option[Int] :: Option[String] :: HNil
? Then why do you request implicit Fill.Aux[length.N, None.type, T]
with Out
-type being the same T
while it should be None.type :: None.type :: None.type :: HNil
.
Try
def emptyList(length: Nat)(
implicit fill: Fill[length.N, None.type]
): fill.Out = {
HList.fill(length)(None)
}
emptyList(natLength[OL]) //None :: None :: None :: HNil
*->*[Option]#λ
can be context bound in def natLength
.