Scala 从HList检索元素(同时保留其类型)的函数
我有这种类型,将通过shapeless生成:Scala 从HList检索元素(同时保留其类型)的函数,scala,shapeless,hlist,Scala,Shapeless,Hlist,我有这种类型,将通过shapeless生成: type hlistt = STUDENT.type :: AUTO_LOANS.type :: HNil 基本上,我有一堆case对象扩展了一个trait,所以我设法创建了一个方法,将所有case对象的实例作为HList提供给我 然后使用import shapeless.ops.hlist.Last和init我编写了一个方法,如果值等于字符串“student”,则检索hlist中的一个节点: 问题是,如果调用此方法,将无法从HList获取正确的节
type hlistt = STUDENT.type :: AUTO_LOANS.type :: HNil
基本上,我有一堆case对象扩展了一个trait,所以我设法创建了一个方法,将所有case对象的实例作为HList提供给我
然后使用import shapeless.ops.hlist.Last
和init
我编写了一个方法,如果值等于字符串“student”,则检索hlist中的一个节点:
问题是,如果调用此方法,将无法从HList获取正确的节点类型
getLast(STUDENT :: AUTO_LOANS :: HNil)
该方法工作并返回节点,但类型为off:
Product with Serializable = STUDENT :: HNil
我是否需要一些见证/Aux隐式函数来返回正确的类型?我不太确定您想做什么。鉴于:
type hlistt = STUDENT.type :: AUTO_LOANS.type :: HNil
Last[hlistt]
将解析为自动贷款。键入
(您的真实if分行)
而init
将解析为STUDENT::HNil
(您的false if分支)
这些类型的LUB(最小上界)将是可序列化的产品
,因此您会看到这一点
如果要检查hlist成员的运行时属性,则必须通过使用适当的机制派生相应的typebounds和result类型来遍历它们。在这种情况下,这是已经给出的形状
这是你想要的吗
编辑:
我也刚刚读过
我有一个将动态生成的类型:
你说的“动态”到底是什么意思?因为除非您可以指定一些编译时属性,否则无形状可能不是您要寻找的解决方案。我不太确定您想要做什么。鉴于:
type hlistt = STUDENT.type :: AUTO_LOANS.type :: HNil
Last[hlistt]
将解析为自动贷款。键入
(您的真实if分行)
而init
将解析为STUDENT::HNil
(您的false if分支)
这些类型的LUB(最小上界)将是可序列化的产品
,因此您会看到这一点
如果要检查hlist成员的运行时属性,则必须通过使用适当的机制派生相应的typebounds和result类型来遍历它们。在这种情况下,这是已经给出的形状
这是你想要的吗
编辑:
我也刚刚读过
我有一个将动态生成的类型:
你说的“动态”到底是什么意思?因为除非您可以指定一些编译时属性,否则shapeless可能不是您正在寻找的解决方案。
la
是类型AUTO\u LOANS.type
,init(hl)
是类型STUDENT.type::HNil
,所以
if (la.value == "student") la
else init(hl)
属于Any
(或可序列化的产品)类型
如果要从不同的分支返回不同类型的值,则需要一个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
如果字符串在编译时是已知的,这种方法就可以工作。la
类型为AUTO\u LOANS.type
,init(hl)
类型为STUDENT.type::HNil
,因此
if (la.value == "student") la
else init(hl)
属于Any
(或可序列化的产品)类型
如果要从不同的分支返回不同类型的值,则需要一个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
如果字符串在编译时已知,则此方法有效。这不是再现所描述结果的正确代码。首先,正如所发布的,getLast()
,不是递归的。@jwvh好的观点-我在深夜(我的时间)写了这篇文章,最初考虑的是递归的fn。我的意思是将init(hl)
包装成getLast(init(hl))
这不是复制您描述的结果的正确代码。首先,正如所发布的,getLast()
,不是递归的。@jwvh好的观点-我在深夜(我的时间)写了这篇文章,最初考虑的是递归的fn。我的意思是把init(hl)
包装成getLast(init(hl))
你已经非常接近我想要的了。你知道我为什么不能这样做吗:if(last(hlist).value==“student”)Some(last(hlist))else-getLastOrNone(init(hlist))
并为HNil添加一个案例。我的类型不匹配。我正在尝试遍历HList,并按值而不是按类型查找节点。问题是,在编译时您不知道函数的输出类型是什么,因为它取决于运行时值。您使用HList
的动机是什么?我想在示例代码中保留Car
和Student
的类型。我遇到的实际问题是给一个字符串“student”或“car”获取正确的单例ie student或car。我在这些单例类型上定义了类型类,这就是为什么我非常努力地保留类型。我还打算绘制一些“汽车”->汽车“学生”的地图->学生们,当我得到一个文本时,我可以用它作为一个键来获得合适的类型。从技术上来说,我想你可以构造一个函数,从某个hlista::B::C::HNil
到a:+:B:+:C:+:Unit:+:CNil
,然后找到某个谓词多函数的第一个匹配项或返回Unit
。但是因为你是基于运行时的值,所以我认为你不能直接做到。该函数的返回类型是什么?所以它更倾向于一个解决方案,正如Dmytro所说的那样。这是我的障碍:不知道该方法的类型:(你已经非常接近我想要的了。你知道我为什么不能做:if(last(hlist)。value==“student”)Some(last(hlist))else getLastOrNone(init(hlist))
并为HNil
添加了一个案例。我得到了一个类型不匹配。我正在尝试遍历HList并按值而不是按类型查找节点。问题是,在编译时您不知道函数的输出类型是什么,因为它取决于运行时值。您使用HList
的动机是什么?我想知道要保留Car的类型