首页 > 解决方案 > 从 HList 中检索元素的函数(同时保留其类型)

问题描述

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

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

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

然后使用import shapeless.ops.hlist.Lastandinit我编写了一个方法来检索 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)

该方法有效并返回节点,但类型为关闭:

Product with Serializable = STUDENT :: HNil

我需要一些见证/辅助隐式来返回正确的类型吗?

标签: scalashapelesshlist

解决方案


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

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


推荐阅读