首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将HList转换为HList of HLists

将HList转换为HList of HLists
EN

Stack Overflow用户
提问于 2014-07-02 17:06:20
回答 1查看 203关注 0票数 4

如何将HList转换为HList of HLists,如下面的片段所示。

代码语言:javascript
复制
import shapeless._
import Nat._

case class A(i: Int)
case class B(str: String)
case class C(i: Int, str: String)

type Input = A :: B :: C :: HNil
val in: Input = A(1) :: B("b") :: C(2, "c") :: HNil

type X = A :: HNil
val x: X = A(1) :: HNil

type Y = A :: B :: HNil // could also be B :: HNil
val y: Y = A(1) :: B("b") :: HNil

type Z = A :: C :: HNil // could also be B :: C :: HNil
val z: Z = A(1) :: C(2, "c") :: HNil

type Output = X :: Y :: Z :: HNil
val out: Output = x :: y :: z :: HNil

// Illustrates what I want to accomplish.
def build(in: Input) : Output = {
  val x: X = in(_0) :: HNil
  val y: Y = in(_0) :: in(_1) :: HNil
  val z: Z = in(_0) :: in(_2) :: HNil
  x :: y :: z :: HNil
}

println(build(in) == out) // true


def magic[In <: HList, Out <: HList](in: In) : Out = ???
println(magic[Input, Output](in) == out)

我希望通过Output方法来构建给定的Input,该方法以某种方式映射输入,并以build输出结束。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-07-02 23:10:03

对于自定义类型类来说,这并不是很糟糕。请注意,在某种意义上,我们需要两个“基本案例”-one来启动顶级HList,另一个启动每个内部HList。然后,归纳步骤展示了如何将新项(我们知道如何从输入中提取)添加到我们添加的最后一个HList中。

代码语言:javascript
复制
import shapeless._, ops.hlist.Selector

trait Picker[I <: HList, O <: HList] {
  def apply(i: I): O
}

object Picker {
  implicit def hnilPicker[I <: HList]: Picker[I, HNil] = new Picker[I, HNil] {
    def apply(i: I) = HNil
  }

  implicit def hnilHlistPicker[I <: HList, OT <: HList](implicit
    picker: Picker[I, OT]
  ): Picker[I, HNil :: OT] = new Picker[I, HNil :: OT] {
    def apply(i: I) = HNil :: picker(i)
  }

  implicit def hlistPicker[I <: HList, OHH, OHT <: HList, OT <: HList](implicit
    sel: Selector[I, OHH],
    picker: Picker[I, OHT :: OT]
  ): Picker[I, (OHH :: OHT) :: OT] = new Picker[I, (OHH :: OHT) :: OT] {
    def apply(i: I) = picker(i) match {
      case h :: t => (sel(i) :: h) :: t
    }
  }
}

然后:

代码语言:javascript
复制
def magic[In <: HList, Out <: HList](in: In)(implicit
  picker: Picker[In, Out]
): Out = picker(in)

最后:

代码语言:javascript
复制
scala> println(magic[Input, Output](in))
A(1) :: HNil :: A(1) :: B(b) :: HNil :: A(1) :: C(2,c) :: HNil :: HNil

scala> println(magic[Input, Output](in) == out)
true

最好能够只指定输出类型并推断输入类型,但不幸的是,没有方便的方法来实现这一点。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24537035

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档