拆分使用 Prepend[A, B] 连接的 HList
Splitting an HList that was concatenated using Prepend[A, B]
我基本上是在寻找 class 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
我有一个 HList
a
类型 A
和一个 HList
b
类型 B
,我可以找到 prepend: Prepend[A, B]
这样我就可以将它们与 a ++ b
.
连接起来
但是如果我有一个 prepend.Out
类型的 HList
ab
,我该如何提取原始的 A
和 B
?我似乎无法找到一种类型 class 来完成这项工作,也许没有。似乎我需要像 trait Cut[A <: HList, B <: HList, c <: HList]
这样的东西来证明 C
是通过预先挂起 A
到 B
创建的,尽管我不确定我会怎么做关于产生证人。
很像:
def Cut[A <: HList, B <: HList, C <: HList](c: C)(implicit cut: Cut[A, B, C]): (A, B) = ???
您可以使用 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]
然后:
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
我 recently added Remove
类型 class 的 "undo" 操作,在 Prepend
中内置类似的东西可能有意义。
我基本上是在寻找 class 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
我有一个 HList
a
类型 A
和一个 HList
b
类型 B
,我可以找到 prepend: Prepend[A, B]
这样我就可以将它们与 a ++ b
.
但是如果我有一个 prepend.Out
类型的 HList
ab
,我该如何提取原始的 A
和 B
?我似乎无法找到一种类型 class 来完成这项工作,也许没有。似乎我需要像 trait Cut[A <: HList, B <: HList, c <: HList]
这样的东西来证明 C
是通过预先挂起 A
到 B
创建的,尽管我不确定我会怎么做关于产生证人。
很像:
def Cut[A <: HList, B <: HList, C <: HList](c: C)(implicit cut: Cut[A, B, C]): (A, B) = ???
您可以使用 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]
然后:
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
我 recently added Remove
类型 class 的 "undo" 操作,在 Prepend
中内置类似的东西可能有意义。