Reputation: 1989
I want to have a generic list of different types and I want to get objects with specific type.
I have this structure:
trait Parent
case class A() extends Parent
case class B() extends Parent
case class C() extends Parent
I may define different lists with different size of:
val list:List[Parent] = A() :: B() :: C() :: C() ::Nil //or any size or ordering
I want to cast this in runtime to Hlist of A,B,C,C. .toHlist[] need types of elements which should be infer in runtime. What would be Shapeless way of it? Is there any way to convert it to tuples?
Upvotes: 4
Views: 1905
Reputation: 572
The following function can convert your list to a HList:
def listToHList(x: List[_]): HList = {
if(x == Nil) HNil
else x.head :: listToHList(x.tail)
}
For your sample, you can use it like the following:
listToHList(list).asInstanceOf[A :: B :: C :: HNil]
Upvotes: 0
Reputation: 127711
You can't do it. Note that
should be infer in runtime
is a contradiction. Type inference works in compile time only.
In other words, when you write something like
val list: A :: B :: C :: C :: HNil = ...
the type of list
variable is known at compile time. It is impossible to assign a type to a variable at runtime, it just doesn't make sense. Suppose it would be possible, and you would have a magical method toHlistMagical
:
val list: List[Parent] = A() :: B() :: C() :: C() :: Nil
val hlist = list.toHlistMagical // infers to A :: B :: C :: C :: HNil
Now let's change it a bit:
def getHlist(list: List[Parent]) = list.toHlistMagical
Now what return type do you expect for this function to have? Bear in mind that it can be called with various lists, not only those which contain A
, B
, C
, C
instances in this order:
getHlist(C() :: B() :: A() :: A() :: Nil)
It could be Any
, but then you can just go with List
anyway because there is no HList
anymore, so you don't get any extra type safety.
That's the reason why toHlist
needs types:
def getHlist(list: List[Parent]) = list.toHlist[A :: B :: C :: C :: HNil]
getHlist
now has return type Option[A :: B :: C :: C :: HNil]
, because you specified the exact type you want, and toHlist
will be able to perform runtime validation of the list
structure and return Some
if the list does actually contain these types in this order or None
if it does not.
Upvotes: 2