为 HList 类型构建类型类实例列表
Build list of typeclass instances for HList type
我正在尝试改进我们 API 之一的类型。我想创建具有以下签名的数据提取器:
def runIt[T <: HList](id: Int): T = ???
它应该获取某些实体的调用外部服务器和 return 具有所需数据的 HList。第一项任务是为所需功能构建 API 参数列表。
这是我做的:
import shapeless._
import shapeless.ops.hlist._
trait Feature
trait FeatureFetcher[T] {
def name: String
}
trait F1 extends Feature
trait F2 extends Feature
implicit case object f1Fetcher extends FeatureFetcher[F1] {
val name = "f1name"
}
implicit case object f2Fetcher extends FeatureFetcher[F2] {
val name = "f2name"
}
def makeIt[T <: HList](id: Int)
(implicit liftAll: LiftAll[FeatureFetcher, T]) = {
// I need this, but it does not compile here
// liftAll.instances.toList.map(_.name).mkString(",")
liftAll.instances
}
makeIt[F1 :: F2 :: HNil](1).toList.map(_.name).mkString(",")
它确实有效。但是当我将 .toList
移动到 makeIt
函数时,我得到错误
Error:(25, 21) could not find implicit value for parameter toTraversableAux: shapeless.ops.hlist.ToTraversable.Aux[liftAll.Out,List,Lub]
liftAll.instances.toList.map(_.name).mkString(",")
如何解决这个问题?
我认为当代码使用 implicit liftAll: LiftAll[FeatureFetcher, T]
调用隐式实例时,LiftAll 的依赖类型 Out of LiftAll 将丢失,因此编译器不知道哪种类型的实例将 return,因此错误。
一个可能的解决方案是使用,使用 shapeless
中的 the
,这应该是更好的隐式方法。
the[liftAll].instances.toList
如果有帮助请告诉我!!
基于 segeljakt,尝试通过 LiftAll.Aux
将 liftAll.Out
传递给 ToTraversable.Aux
def makeIt[In <: HList, Out <: HList](id: Int)(implicit
liftAll: LiftAll.Aux[FeatureFetcher, In, Out],
toTraversable: ToTraversable.Aux[Out, List, FeatureFetcher[_]]
): String = {
liftAll.instances.toList.map(_.name).mkString(",")
}
type In = F1 :: F2 :: HNil
type Out = FeatureFetcher[F1] :: FeatureFetcher[F2] :: HNil
makeIt[In, Out](1)
// res1: String = f1name,f2name
或基于ToElmTypes
case class MakeIt[In <: HList]() {
def apply[Out <: HList](id: Int)(implicit
liftAll: LiftAll.Aux[FeatureFetcher, In, Out],
toTraversable: ToTraversable.Aux[Out, List, FeatureFetcher[_]]
): String = {
liftAll.instances.toList.map(_.name).mkString(",")
}
}
MakeIt[F1 :: F2 :: HNil].apply(1)
我正在尝试改进我们 API 之一的类型。我想创建具有以下签名的数据提取器:
def runIt[T <: HList](id: Int): T = ???
它应该获取某些实体的调用外部服务器和 return 具有所需数据的 HList。第一项任务是为所需功能构建 API 参数列表。
这是我做的:
import shapeless._
import shapeless.ops.hlist._
trait Feature
trait FeatureFetcher[T] {
def name: String
}
trait F1 extends Feature
trait F2 extends Feature
implicit case object f1Fetcher extends FeatureFetcher[F1] {
val name = "f1name"
}
implicit case object f2Fetcher extends FeatureFetcher[F2] {
val name = "f2name"
}
def makeIt[T <: HList](id: Int)
(implicit liftAll: LiftAll[FeatureFetcher, T]) = {
// I need this, but it does not compile here
// liftAll.instances.toList.map(_.name).mkString(",")
liftAll.instances
}
makeIt[F1 :: F2 :: HNil](1).toList.map(_.name).mkString(",")
它确实有效。但是当我将 .toList
移动到 makeIt
函数时,我得到错误
Error:(25, 21) could not find implicit value for parameter toTraversableAux: shapeless.ops.hlist.ToTraversable.Aux[liftAll.Out,List,Lub]
liftAll.instances.toList.map(_.name).mkString(",")
如何解决这个问题?
我认为当代码使用 implicit liftAll: LiftAll[FeatureFetcher, T]
调用隐式实例时,LiftAll 的依赖类型 Out of LiftAll 将丢失,因此编译器不知道哪种类型的实例将 return,因此错误。
一个可能的解决方案是使用,使用 shapeless
中的 the
,这应该是更好的隐式方法。
the[liftAll].instances.toList
如果有帮助请告诉我!!
基于 segeljakt,尝试通过 LiftAll.Aux
将 liftAll.Out
传递给 ToTraversable.Aux
def makeIt[In <: HList, Out <: HList](id: Int)(implicit
liftAll: LiftAll.Aux[FeatureFetcher, In, Out],
toTraversable: ToTraversable.Aux[Out, List, FeatureFetcher[_]]
): String = {
liftAll.instances.toList.map(_.name).mkString(",")
}
type In = F1 :: F2 :: HNil
type Out = FeatureFetcher[F1] :: FeatureFetcher[F2] :: HNil
makeIt[In, Out](1)
// res1: String = f1name,f2name
或基于ToElmTypes
case class MakeIt[In <: HList]() {
def apply[Out <: HList](id: Int)(implicit
liftAll: LiftAll.Aux[FeatureFetcher, In, Out],
toTraversable: ToTraversable.Aux[Out, List, FeatureFetcher[_]]
): String = {
liftAll.instances.toList.map(_.name).mkString(",")
}
}
MakeIt[F1 :: F2 :: HNil].apply(1)