I am playing around with Shapeless and I am trying to compute the (kind-of) powerset of an HList
of Option
s. Basically, I want to interpret the HList
as a set, in which case the Option
value of an element tells me it belongs to the set or not.
For example, given Some(5) :: Some("a") :: HNil
, I want to obtain the following HList
s:
Some(5) :: Some("a") :: HNil
Some(5) :: None :: HNil
None :: Some("a") :: HNil
None :: None :: HNil
I tried the following:
object test2 extends Poly2{
implicit def someA[A,B <: HList] : Case.Aux[Some[A], List[B], List[Option[A] :: B]] = at{(a, hls) =>
val x: List[Option[A] :: B] = hls.flatMap{ hl =>
List(
a :: hl,
None :: hl
)
}
x
}
implicit val none : Case.Aux[None.type, List[HList], List[HList]] = at{(_, hls) =>
hls.map(hl => None :: hl)
}
}
h.foldRight(List(HNil))(test2)
Without success. I get a failed implicit resolution at the foldRight
:
Error:(36, 25) could not find implicit value for parameter folder: shapeless.ops.hlist.RightFolder[Some[Int] :: None.type :: shapeless.HNil,List[shapeless.HNil.type],A$A8.this.test2.type]
h.foldRight(List(HNil))(test2);}
^
I am starting to think that what I want is not possible/makes no sense in Shapeless, because Some[A]
and None
are different types, and I am trying to mix them like they were not (e.g. the List[Option[A] :: B]
in someA
), but I would be very happy to be proven wrong. :)
Update to initial question:
Thanks to @Marth's comment, I realized that my code worked fine, as long as I did not use IntelliJ Scala Worksheet! I used a plain object
and it worked.
Also, I neeed to add a case to the Poly
for Option[A]
. The final code is the following:
object combine1 extends Poly2{
implicit def optionA[A,B <: HList] : Case.Aux[Option[A], List[B], List[Option[A] :: B]] = at{(a, hls) =>
val x: List[Option[A] :: B] = hls.flatMap{ hl => a match {
case Some(_) =>
List(
None :: hl,
a :: hl,
)
case None =>
List(None :: hl)
}
}
x
}
implicit def someA[A,B <: HList] : Case.Aux[Some[A], List[B], List[Option[A] :: B]] = at{(a, hls) =>
val x: List[Option[A] :: B] = hls.flatMap{ hl =>
List(
None :: hl,
a :: hl
)
}
x
}
implicit val none : Case.Aux[None.type, List[HList], List[HList]] = at{(_, hls) =>
hls.map(hl => None :: hl)
}
}