List的运行时转换为HList

时间:2014-12-12 06:48:58

标签: scala types shapeless

我想要一个不同类型的通用列表,我想获得具有特定类型的对象。

我有这个结构:

trait Parent
case class A() extends Parent
case class B() extends Parent
case class C() extends Parent

我可以定义不同大小的不同列表:

val list:List[Parent] = A() :: B() :: C() :: C() ::Nil //or any size or ordering

我想在运行时将其转换为A,B,C,C的Hlist。 .toHlist []需要在运行时推断的元素类型。 什么是无形的方式呢?有没有办法将其转换为元组?

2 个答案:

答案 0 :(得分:3)

你不能这样做。注意

  

应该在运行时推断

是一个矛盾。类型推断仅在编译时

换句话说,当你写一些像

这样的东西
val list: A :: B :: C :: C :: HNil = ...

编译时知道list变量的类型。在运行时不可能为变量赋值,它只是没有意义。假设它是可能的,你会有一个神奇的方法toHlistMagical

val list: List[Parent] = A() :: B() :: C() :: C() :: Nil
val hlist = list.toHlistMagical  // infers to  A :: B :: C :: C :: HNil

现在让我们改变一下:

def getHlist(list: List[Parent]) = list.toHlistMagical

现在你期望这个函数有什么返回类型?请记住,可以使用各种列表调用它,而不仅仅是按以下顺序包含ABCC实例的列表:

getHlist(C() :: B() :: A() :: A() :: Nil)

可能是Any,但是你可以随时使用List,因为不再有HList,所以你没有获得任何额外的类型安全。

这就是toHlist需要类型的原因:

def getHlist(list: List[Parent]) = list.toHlist[A :: B :: C :: C :: HNil]

getHlist现在有返回类型Option[A :: B :: C :: C :: HNil],因为您指定了所需的确切类型,toHlist将能够执行list结构的运行时验证并返回Some如果列表确实按此顺序包含这些类型,或None如果不包含这些类型。

答案 1 :(得分:0)

以下功能可以将您的列表转换为HList:

def listToHList(x: List[_]): HList = {
  if(x == Nil) HNil
  else x.head :: listToHList(x.tail)
}

对于您的示例,您可以按以下方式使用它:

listToHList(list).asInstanceOf[A :: B :: C :: HNil]