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

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获取正确的节

我有这种类型,将通过shapeless生成:

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。我在这些单例类型上定义了类型类,这就是为什么我非常努力地保留类型。我还打算绘制一些“汽车”->汽车“学生”的地图->学生们,当我得到一个文本时,我可以用它作为一个键来获得合适的类型。从技术上来说,我想你可以构造一个函数,从某个hlist
a::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的类型