拆分使用Prepend [A,B]连接的HList

Mic*_*jac 8 scala shapeless

我基本上寻找类型类的反面Prepend[A, B].

如果我有类似的东西:

type A = String :: Int :: HNil
type B = Boolean :: Double :: HNil

val a: A = "a" :: 1 :: HNil
val b: B = false :: 2.1 :: HNil

scala> val ab = a ++ b
ab: shapeless.::[String,shapeless.::[Int,shapeless.::[Boolean,shapeless.::[Double,shapeless.HNil]]]] = a :: 1 :: false :: 2.1 :: HNil
Run Code Online (Sandbox Code Playgroud)

我有一个HList a类型AHList b类型B,我可以找到一个prepend: Prepend[A, B]这样我可以连接它们a ++ b.

但如果我有一个HList ab类型prepend.Out,我怎么能提取原始AB?我似乎无法找到一个完成这项工作的类型类,也许没有一个.好像我需要像trait Cut[A <: HList, B <: HList, c <: HList]那个证人C已被申请中预创建AB,虽然我不知道我怎么会去约产生证人.

非常像:

def Cut[A <: HList, B <: HList, C <: HList](c: C)(implicit cut: Cut[A, B, C]): (A, B)  = ???
Run Code Online (Sandbox Code Playgroud)

Tra*_*own 6

您可以通过以下方式直接完成此操作Split:

import shapeless._, ops.hlist.{ Length, Prepend, Split }

class UndoPrependHelper[A <: HList, B <: HList, C <: HList, N <: Nat] {
  def apply(c: C)(implicit split: Split.Aux[C, N, A, B]): (A, B) = split(c)
}

def undoPrepend[A <: HList, B <: HList](implicit
  prepend: Prepend[A, B],
  length: Length[A]
) = new UndoPrependHelper[A, B, prepend.Out, length.Out]
Run Code Online (Sandbox Code Playgroud)

然后:

scala> type A = Int :: String :: Symbol :: HNil
defined type alias A

scala> type B = List[Int] :: Option[Double] :: HNil
defined type alias B

scala> type C = Int :: String :: Symbol :: List[Int] :: Option[Double] :: HNil
defined type alias C

scala> val a: A = 1 :: "foo" :: 'bar :: HNil
a: A = 1 :: foo :: 'bar :: HNil

scala> val b: B = List(1, 2, 3) :: Option(0.0) :: HNil
b: B = List(1, 2, 3) :: Some(0.0) :: HNil

scala> val c: C = a ++ b
c: C = 1 :: foo :: 'bar :: List(1, 2, 3) :: Some(0.0) :: HNil

scala> val (newA: A, newB: B) = undoPrepend[A, B].apply(c)
newA: A = 1 :: foo :: 'bar :: HNil
newB: B = List(1, 2, 3) :: Some(0.0) :: HNil
Run Code Online (Sandbox Code Playgroud)

最近Remove类型类添加了"撤消"操作,并且内置类似内容可能是有意义的Prepend.