从 HList 中检索元素的函数(同时保留其类型)
Function that retrieves element from HList (while preserving its type)
我有这种类型,它将通过 shapeless 生成:
type hlistt = STUDENT.type :: AUTO_LOANS.type :: HNil
基本上我有一堆扩展特征的案例对象,所以我设法创建了一个方法,它给我所有案例对象的实例作为一个 HList
然后使用 import shapeless.ops.hlist.Last
和 init
我写了一个方法来检索 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)
该方法有效并且 returns 节点但类型已关闭:
Product with Serializable = STUDENT :: HNil
我需要一些 Witness/Aux 隐含到 return 正确的类型吗?
我不太确定你想做什么。给定:
type hlistt = STUDENT.type :: AUTO_LOANS.type :: HNil
Last[hlistt]
将解析为 AUTO_LOANS.type
(您的 true if 分支)
而 init
将解析为 STUDENT :: HNil
(如果分支为 false)
这些类型的 LUB(最小上限)将为 Product with Serializable
,这就是您看到的原因。
如果您想检查 hlist 成员的运行时 属性,您必须通过使用适当的机制派生适当的类型边界和结果类型。在这种情况下,shapeless 已经给出了。
https://scalafiddle.io/sf/fdtn3cz/0
这是你想要的吗?
编辑:
我也刚读
I have this type which will be generated dynamically:
"dynamically" 到底是什么意思?因为除非您可以指定一些编译时属性,否则 shapeless 可能不是您正在寻找的解决方案。
la
是AUTO_LOANS.type
类型,init(hl)
是STUDENT.type :: HNil
类型,所以
if (la.value == "student") la
else init(hl)
类型为 Any
(或 Product with Serializable
)。
如果您想 return 来自不同分支的不同类型的值,您需要 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
如果字符串在编译时已知,则此方法有效。
我有这种类型,它将通过 shapeless 生成:
type hlistt = STUDENT.type :: AUTO_LOANS.type :: HNil
基本上我有一堆扩展特征的案例对象,所以我设法创建了一个方法,它给我所有案例对象的实例作为一个 HList
然后使用 import shapeless.ops.hlist.Last
和 init
我写了一个方法来检索 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)
该方法有效并且 returns 节点但类型已关闭:
Product with Serializable = STUDENT :: HNil
我需要一些 Witness/Aux 隐含到 return 正确的类型吗?
我不太确定你想做什么。给定:
type hlistt = STUDENT.type :: AUTO_LOANS.type :: HNil
Last[hlistt]
将解析为 AUTO_LOANS.type
(您的 true if 分支)
而 init
将解析为 STUDENT :: HNil
(如果分支为 false)
这些类型的 LUB(最小上限)将为 Product with Serializable
,这就是您看到的原因。
如果您想检查 hlist 成员的运行时 属性,您必须通过使用适当的机制派生适当的类型边界和结果类型。在这种情况下,shapeless 已经给出了。
https://scalafiddle.io/sf/fdtn3cz/0
这是你想要的吗?
编辑: 我也刚读
I have this type which will be generated dynamically:
"dynamically" 到底是什么意思?因为除非您可以指定一些编译时属性,否则 shapeless 可能不是您正在寻找的解决方案。
la
是AUTO_LOANS.type
类型,init(hl)
是STUDENT.type :: HNil
类型,所以
if (la.value == "student") la
else init(hl)
类型为 Any
(或 Product with Serializable
)。
如果您想 return 来自不同分支的不同类型的值,您需要 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
如果字符串在编译时已知,则此方法有效。