所以我想尝试这样的事情:
@ import shapeless._
import shapeless._
@ case class A(); case class B(); case class C()
defined class A
defined class B
defined class C
case class Stuff(a: List[A], b: B, c: List[C])
@ def stuffs[H <: HList](hl:H)(
implicit
pb:Partition[H,B],
pa:Partition[H,List[A]],
pc:Partition[H,List[C]],
tl: ToTraversable[H, List]
):List[Stuff] =
hl.filter[B].to[List].map {
b =>
Stuff(
a = hl.filter[List[A]].to[List].flatten,
b = b,
c = hl.filter[List[C]].to[List]flatten
)
}
Compilation Failed
Main.scala:374: could not find implicit value for parameter ts: shapeless.ops.hlist.ToTraversable[pb.Prefix,List]
hl.filter[B].to[List].map {
^
Main.scala:377: could not find implicit value for parameter ts: shapeless.ops.hlist.ToTraversable[pa.Prefix,List]
a = hl.filter[List[A]].to[List].flatten,
我理解,to[List]
,hl.filter[B]
和hl.filter[List[A]]
的结果中hl.filter[List[C]]
需要一些证据pb.Prefix
,{{ 1}}和pa.Prefix
,但那些不能在同一个参数列表中使用,所以不确定在这里可以做什么
根据杰里米的回应更新:
这很有效:
pc.Prefix
但这没有,这是有意义的(它允许定义函数但在尝试使用它时失败仍然很奇怪):
@ def stuffs[H <: HList, Prefix <: HList, Suffix <: HList] (hl:H)(
implicit
pb:Partition.Aux[H,List[A],Prefix, Suffix ],
prefixToTraversable: ToTraversable[Prefix, List]
) = hl.filter[List[A]].to[List]
defined function stuffs
@ stuffs(List(A()) :: List(A()) :: B() :: HNil)
res30: List[List[A]] = List(List(A()), List(A()))
@ def stuffs[H <: HList, Prefix <: HList, Suffix <: HList] (hl:H)(
implicit
pb:Partition.Aux[H,B,Prefix, Suffix ],
prefixToTraversable: ToTraversable[Prefix, List]
) = hl.filter[B].to[List]
defined function stuffs
@ stuffs(List(A()) :: List(A()) :: B() :: HNil)
res33: List[B] = List(B())
然后我试了一下:
@ def stuffs[H <: HList, Prefix <: HList, Suffix <: HList] (hl:H)(
implicit
pa:Partition.Aux[H,List[A],Prefix, Suffix ],
pb:Partition.Aux[H,B,Prefix, Suffix ],
prefixToTraversable: ToTraversable[Prefix, List]
) = (hl.filter[List[A]].to[List], hl.filter[B].to[List])
defined function stuffs
@ stuffs(List(A()) :: List(A()) :: B() :: HNil)
Compilation Failed
Main.scala:375: could not find implicit value for parameter pb: shapeless.ops.hlist.Partition.Aux[shapeless.::[List[cmd1.A],shapeless.::[List[cmd1.A],shapeless.::[cmd1.B,shapeless.HNil]]],cmd1.B,Prefix,Suffix]
stuffs(List(A()) :: List(A()) :: B() :: HNil)
^
最后一个片段对我有意义,为什么不起作用?
答案 0 :(得分:1)
如果您需要使用无形证明的输出类型,您可以使用证明的相应Aux
类型和其他类型参数来获取相同参数列表中该输出类型的证明:
def stuffs[H <: HList, Prefix <: HList, Suffix <: HList](implicit
pb: Partition.Aux[H, B, Prefix, Suffix],
traversablePrefix: ToTraversable[Prefix, List]
....
)
大多数证据类型都有Aux
类型用于此目的。
答案 1 :(得分:1)
你的最后一次尝试非常接近。 @Jeremy对于Partition
操作的输出类型需要类型变量是正确的。您还需要指定ToTraversable
操作的输出类型,以确定转换结果的元素类型,
import shapeless._
import ops.hlist._, ops.traversable._
case class A()
case class B()
case class C()
case class Stuff(a: List[A], b: B, c: List[C])
def stuffs[H <: HList, PA <: HList, SA <: HList, PB <: HList, SB <: HList, PC <: HList, SC <: HList](hl:H)
(implicit
pa: Partition.Aux[H, List[A], PA, SA],
pb: Partition.Aux[H, B, PB, SB],
pc: Partition.Aux[H, List[C], PC, SC],
prefixToTraversableA: ToTraversable.Aux[PA, List, List[A]],
prefixToTraversableB: ToTraversable.Aux[PB, List, B],
prefixToTraversableC: ToTraversable.Aux[PC, List, List[C]]
): List[Stuff] = {
val as: List[A] = hl.filter[List[A]].to[List].flatten
val bs: List[B] = hl.filter[B].to[List]
val cs: List[C] = hl.filter[List[C]].to[List].flatten
bs.map(Stuff(as, _, cs))
}
val hl = List(A(), A()) :: B() :: List(C()) :: B() :: List(C(), C()) ::HNil
val ss = stuffs(hl)
val expected =
List(
Stuff(List(A(), A()), B(), List(C(), C(), C())),
Stuff(List(A(), A()), B(), List(C(), C(), C()))
)
assert(ss == expected)