首页 文章

从HList检索元素的函数(同时保留其类型)

提问于
浏览
0

我有这种类型将通过无形生成:

type hlistt = STUDENT.type :: AUTO_LOANS.type :: HNil

基本上我有一堆案例对象扩展一个特征,所以我设法创建一个方法,它给我所有案例对象的实例作为一个HList

然后使用 import shapeless.ops.hlist.Lastinit 我写了一个方法来检索HList中的一个节点,如果该值等于字符串"student":

def getLast(hl:hlistt) = {
  val last0=Last[hlistt]
  val la=last0(hl)

  if (la.value == "student") la
  else init(hl)
}

问题是,如果我调用此方法,我将无法从HList获取正确的节点类型 .

getLast(STUDENT :: AUTO_LOANS :: HNil)

该方法工作并返回节点但类型为off:

Product with Serializable = STUDENT :: HNil

Do I need some Witness/Aux implicits to return the correct type?

2 回答

  • 1

    la 的类型为 AUTO_LOANS.typeinit(hl) 的类型为 STUDENT.type :: HNil ,所以

    if (la.value == "student") la
    else init(hl)
    

    的类型为 Any (或 Product with Serializable ) .

    如果您想从不同的分支返回不同类型的值,则需要 Poly .

    import shapeless.{Poly1, Witness}
    
    object myPoly extends Poly1 {
      implicit def studentCase: Case.Aux[Witness.`"student"`.T, STUDENT.type] = 
        at(_ => STUDENT)
      implicit def autoLoansCase: Case.Aux[Witness.`"auto-loans"`.T, AUTO_LOANS.type] = 
        at(_ => AUTO_LOANS)
    }
    
    import shapeless.syntax.singleton._
    println(
      myPoly("student".narrow)
    ) // STUDENT
    
    println(
      myPoly("auto-loans".narrow)
    ) // AUTO_LOANS
    
    // println(
    //   myPoly("abc".narrow)
    // )  // doesn't compile
    

    如果字符串在编译时已知,则此方法有效 .

  • 1

    我不太清楚你想做什么 . 鉴于:

    type hlistt = STUDENT.type :: AUTO_LOANS.type :: HNil
    

    Last[hlistt] 将解析为 AUTO_LOANS.type (你的真实if分支),而 init 将解析为 STUDENT :: HNil (你的假if分支)

    这些类型的LUB(最小上限)将是 Product with Serializable 所以这就是你看到的原因 .

    如果要检查hlist成员的运行时属性,则必须通过使用适当的机制导出适当的类型和结果类型 . 在这种情况下,已经是无形的 .

    https://scalafiddle.io/sf/fdtn3cz/0

    这是你想要的吗?

    编辑:我也读过

    我有这种动态生成的类型:

    你是什么意思“动态”?因为除非您可以指定一些编译时属性,否则shapeless可能不是您正在寻找的解决方案 .

相关问题