分区

时间:2015-12-04 23:14:44

标签: scala shapeless

所以我想尝试这样的事情:

@ 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)
      ^

最后一个片段对我有意义,为什么不起作用?

2 个答案:

答案 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)