Suppose I have an abitrary KList, which for the sake of argument has type constructor Option[_], ie;
type Example = Option[Int] :: Option[String] :: HNil
Is there a way I can retrieve an Hlist made of the type parameters?
type Params = Int :: String :: HNil
So, for example I might be able to define some sort of arbitrary getOrElse method
getOrElse(ex:Example, default:Params):Params
Now I'm looking for something possibly of a form like this (or similar as the type structure I propose might not be feasible).
case class MyOptionList[L <: HList](maybes:L) {
type Concrete = {somehow the hlist params types as an Hlist}
def getOrElse(default:Concrete):Concrete = ???
}
I'm not Miles, but it's possible to accomplish what you're trying to do pretty elegantly with Shapeless's Comapped
:
import shapeless._, ops.hlist.Comapped
case class MyOptionList[L <: HList, C <: HList](maybes: L)(
implicit val comapped: Comapped.Aux[L, Option, C]
) {
def getOrElse(default: C): C = default // Not a useful implementation
}
And then:
scala> val x: Int :: HNil = MyOptionList(Option(1) :: HNil).getOrElse(2 :: HNil)
x: shapeless.::[Int,shapeless.HNil] = 2 :: HNil
Note that in some cases it can be more convenient to put the constraint on the method:
case class MyOptionList[L <: HList](maybes: L) {
def getOrElse[C <: HList: ({ type l[x] = Comapped.Aux[L, Option, x] })#l](
default: C
): C = default
}
Here the usage is the same, but you don't have the extra type parameter on the case class. If you want to use this approach but constrain the creation of MyOptionList
to disallow non-Option
members, you could use L <: HList: *->*[Option]#λ
in its type parameter list.
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