HList partition that was merged using Prepend [A, B]

I am essentially looking for the opposite of a class like Prepend[A, B] .

If I have something like:

 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 

I have HList a type a and HList b type b , I can find prepend: Prepend[A, B] so that I can combine them with a ++ b .

But if I have an HList ab type prepend.Out , how can I extract the original a and b ? It seems I can’t find a type class that does the job, and maybe not. It looks like I will need something like trait Cut[A <: HList, B <: HList, c <: HList] , indicating that C was created with a prior expectation of a to b , although I'm not sure how I will generate witnesses.

Very rude, like:

 def Cut[A <: HList, B <: HList, C <: HList](c: C)(implicit cut: Cut[A, B, C]): (A, B) = ??? 
+8
scala shapeless
source share
1 answer

You can do this quite simply with 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] 

And then:

 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 

I recently added a undo operation for a class of type Remove , and it might make sense to have something similar built into Prepend .

+5
source share

All Articles