我有这种类型,可以通过无形生成:
type hlistt = STUDENT.type :: AUTO_LOANS.type :: HNil
基本上,我有一堆扩展特性的case对象,因此我设法创建了一种方法,该方法将所有case对象的实例作为HList给出
然后使用import shapeless.ops.hlist.Last
和init
写了一个方法,如果值等于字符串“ student”,则可以检索HList中的一个节点:
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
我需要一些见证/辅助隐式返回正确的类型吗?
答案 0 :(得分:1)
我不太确定您想做什么。鉴于:
type hlistt = STUDENT.type :: AUTO_LOANS.type :: HNil
Last[hlistt]
将解析为AUTO_LOANS.type
(如果为分支则为真)
而init
将解析为STUDENT :: HNil
(如果为分支则为假)
这些类型的LUB(最小上限)将为Product with Serializable
,所以这就是您看到它的原因。
如果要检查hlist成员的运行时属性,则必须通过使用适当的机制派生适当的类型边界和结果类型来进行线程化。在这种情况下,它是无形的。
https://scalafiddle.io/sf/fdtn3cz/0
这是您想要的吗?
编辑: 我也刚读
我有这种类型,可以动态生成:
“动态”到底是什么意思?因为除非您可以指定一些编译时属性,否则shapeless可能不是您想要的解决方案。
答案 1 :(得分:1)
la
的类型为AUTO_LOANS.type
,init(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
如果在编译时知道字符串,则此方法有效。