Alors, j'ai trouvé une solution qui fonctionne pour mon cas, en déclarant ma propre Union
(copier/pâtes pour la victoire) et ajouter un attribut qui donne à l'SelectAll
exemple
trait SelectableUnion[L <: HList, M <: HList] extends DepFn2[L, M] with Serializable {
type Out <: HList
def selectL: SelectAll[Out, L]
def selectM: SelectAll[Out, M]
}
trait LowPriorityUnion {
type Aux[L <: HList, M <: HList, Out0 <: HList] = SelectableUnion[L, M] {type Out = Out0}
}
object SelectableUnion extends LowPriorityUnion {
def apply[L <: HList, M <: HList](implicit union: SelectableUnion[L, M]): Aux[L, M, union.Out] = union
// let ∅ ∪ M = M
implicit def hlistUnion[M <: HList]: Aux[HNil, M, M] =
new SelectableUnion[HNil, M] {
type Out = M
def apply(l: HNil, m: M): Out = m
override def selectL: SelectAll[M, HNil] = SelectAll.hnilSelectAll
override def selectM: SelectAll[M, M] = new SelectAll[M, M] {
override def apply(t: M): M = t
}
}
// let (H :: T) ∪ M = H :: (T ∪ M) when H ∉ M
implicit def hlistUnion1[H, T <: HList, M <: HList]
(implicit
u: SelectableUnion[T, M],
f: FilterNot.Aux[M, H, M]
): Aux[H :: T, M, H :: u.Out] =
new SelectableUnion[H :: T, M] {
type Out = H :: u.Out
def apply(l: H :: T, m: M): Out = l.head :: u(l.tail, m)
override def selectL: SelectAll[::[H, u.Out], ::[H, T]] = new SelectAll[H :: u.Out, H :: T] {
override def apply(t: H :: u.Out): H :: T = (t.head) :: u.selectL(t.tail)
}
override def selectM: SelectAll[::[H, u.Out], M] = new SelectAll[H :: u.Out, M] {
override def apply(t: ::[H, u.Out]): M = u.selectM.apply(t.tail)
}
}
// let (H :: T) ∪ M = H :: (T ∪ (M - H)) when H ∈ M
implicit def hlistUnion2[H, T <: HList, M <: HList, MR <: HList]
(implicit
r: Remove.Aux[M, H, (H, MR)],
u: SelectableUnion[T, MR]
): Aux[H :: T, M, H :: u.Out] =
new SelectableUnion[H :: T, M] {
type Out = H :: u.Out
def apply(l: H :: T, m: M): Out = l.head :: u(l.tail, r(m)._2)
override def selectL: SelectAll[::[H, u.Out], ::[H, T]] = new SelectAll[H :: u.Out, H :: T] {
override def apply(t: H :: u.Out): H :: T = (t.head) :: u.selectL(t.tail)
}
override def selectM: SelectAll[::[H, u.Out], M] = new SelectAll[H :: u.Out, M] {
override def apply(t: ::[H, u.Out]): M = r.reinsert(t.head, u.selectM(t.tail))
}
}
}
et vous pouvez écrire
def selectFromUnion[E <: HList, F <: HList](u: SelectableUnion[E, F]): SelectAll[u.Out, E] = u.selectL
Pouvez-vous dire ce que vous entendez par 'Union' ici? Ce que vous avez écrit ne ressemble pas à un coproduit étiqueté sans forme. Voulez-vous dire quelque chose comme «Soit» où vous avez juste un de «E» et «F»? Ou quelque chose comme '(,)' où vous avez à la fois 'E' et' F'? –
'Union' est ici une instance de la classe' shapeless.ops.hlist.Union'. Comme je suis nouveau à shapeless, peut-être - probablement - j'ai manqué quelque chose dans la signature de la fonction? – Molochdaa