I have a HList
of coproducts that looks like this:
(A : : B : : CNil) :: (Foo : : Bar : : CNil) :: HNil
This HList
will be a value in my program. E.g.,:
val myhlist: (A : : B : : CNil) :: (Foo : : Bar : : CNil) :: HNil = ???
I have another HList of coproducts, that looks like this:
(A : : CNil) :: (Bar : : CNil) :: HNil
However, this HList will not be a value throughout the program; it only exists in the type level.
I want to zip these two HLists with this zipping function:
def zipFn[A <: Coproduct, B <: Coproduct](a: A)(implicit basis: Basis[A, B]) = {
a.deembed[B]
}
A
is an element from the former HList (which will have values throughout the program), and B
is an element from the latter HList. I want to zip values (A
s) with types (B
s).
Might be a very simple question but somehow I am troubled with this?
Any pointers?
--
My current idea was to use a curried polymorphic function in Shapeless; something like:
object myZipFn extends Poly1 {
implicit def default[A <: Coproduct, B <: Coproduct](implicit basis: Basis[A, B]) = at[A] { a => a.deembed[B] }
}
val curried = Poly.curried(myZipFn)
but doesn't make much sense since default
asks for A and B at the same time.
My idea would be to take in B
(the type with no value) generically first, then return a new function that asks for A
as a value, and then we have both.
Thanks
CodePudding user response:
.zipWith
accepts Poly2
, not Poly1
. So myZipFn
should be
object myZipFn extends Poly2 {
implicit def default[A <: Coproduct, B <: Coproduct](implicit
basis: Basis[A, B]
): Case.Aux[A, B, basis.Out] = at[A, B] { (a, _) => a.deembed[B] }
}
At the not necessary 2nd argument of .zipWith
(because you have the 2nd HList only on type level, not on value level) you can substitute an HList of nulls (but typed properly)
val myhlist: (A : : B : : CNil) :: (Foo : : Bar : : CNil) :: HNil = ???
type hlist1 = (A : : CNil) :: (Bar : : CNil) :: HNil
object nullPoly extends Poly0 {
implicit def default[A]: Case0[A] = at(null.asInstanceOf[A])
}
val nullHlist: hlist1 = FillWith[nullPoly.type, hlist1].apply()
myhlist.zipWith(nullHlist)(myZipFn)
Alternatively, if you don't want to have an HList of nulls, you'll have to define custom Zip
/ZipWith
type class for value/type-level 1st argument and type-level 2nd argument.
Other use cases of FillWith
/nullPoly
trick:
How to obtain all possible members of a coproduct
Scala - looping over case class names to use as type parameters
How to get field names and field types from a Generic Type in Scala?
Is it possible to have a variable type list in Scala?
Get case class field's name and type with shapeless
How to pass into generic type using a Symbol or Type object into a generic typed function?