【问题标题】:Scala: Question about shapeless to tranform HList to ListScala:关于将 HList 转换为 List 的无形问题
【发布时间】:2018-11-14 21:16:05
【问题描述】:

我是 shapeless 的新手(在 scala 的学习曲线中仍然处于低水平...),我很难使用 shapeless

import shapeless._
case class FooBar[T](foo: String, bar: T)
val hl = 0 :: FooBar("A", "one") :: FooBar("B", 1) :: "0" :: FooBar("C", "two") :: HNil
val l = hl.filter[FooBar[String]].toList
println(l) //List(FooBar(A,one), FooBar(C,two))

效果很好

下一步,我想把它放在函数中,比如

def filter[T](hl: HList): List[FooBar[T]] = ???

所以我可以简化调用

filter[String](hl)
filter[Int](hl)

我天真地测试过

def filter[T](hl: HList): List[FooBar[T]] = {
  hl.filter[FooBar[T]].toList
}

给了

 could not find implicit value for parameter partition: shapeless.ops.hlist.Partition[shapeless.HList,FooBar[T]]

在尝试了一些隐式之后,我仍然没有找到正确的方法

你有什么想法吗?

谢谢!

【问题讨论】:

    标签: scala implicit shapeless hlist


    【解决方案1】:

    如果你缺少一些隐式,那么在你的方法中你应该假设它们被提供了。说方法的参数只是HList 类型(而不是一些特定的L <: HList)太粗略了。

    由于您可能想指定T 而不是指定L(预计会推断出L)尝试使用类型类+扩展方法

    import shapeless._
    import shapeless.ops.hlist.{Partition, ToTraversable}
    
    case class FooBar[T](foo: String, bar: T)
    val hl = 0 :: FooBar("A", "one") :: FooBar("B", 1) :: "0" :: FooBar("C", "two") :: HNil
    
    trait FilterFooBar[L <: HList, T] {
      def apply(l: L): List[FooBar[T]]
    }
    
    object FilterFooBar {
      implicit def mkFilterFooBar[L <: HList, T, Prefix <: HList, Suffix <: HList](implicit
        partition: Partition.Aux[L, FooBar[T], Prefix, Suffix],
        toTraversable: ToTraversable.Aux[Prefix, List, FooBar[T]]
      ): FilterFooBar[L, T] = _.filter.toList    
    }
    
    implicit class FilterFooBarOp[L <: HList](l: L) {
      def filterFooBar[T](implicit filterFooBarInstance: FilterFooBar[L, T]): List[FooBar[T]] = 
        filterFooBarInstance(l)
    }
    
    println(hl.filterFooBar[String]) // List(FooBar(A,one), FooBar(C,two))
    println(hl.filterFooBar[Int]) // List(FooBar(B,1))
    

    【讨论】:

    • 作为一个喜欢无形的人,我很伤心,做这件事太复杂了。如果有一种方法可以只指定一个类型参数(并保留其余的推断),那就太好了,这样就没有必要创建一个新的类型类,其唯一目的是关闭 Prefix 和 @987654328 @。 +1
    • 谢谢!确实有很多代码,但我什至没有想过要使用 typeclass。不错的“技巧”,可能对其他情况有用
    • 好吧,代码可能看起来很吓人,但每一步都很简单。编译器说它找不到Partition,所以我在你的方法中添加了这个隐式。然后ToTraversable也是如此。我查看了PartitionToTraversable 的定义并相应地指定了它们的类型参数(并在您的方法中添加了泛型)。然后我意识到有必要在调用时同时指定TL(以及其他泛型),并将您的方法替换为类型类+扩展方法,以便推断L,并且只有T 应该被指定。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-24
    • 1970-01-01
    • 2015-02-10
    • 1970-01-01
    • 2018-02-20
    相关资源
    最近更新 更多