2017-05-24 3 views
0

J'ai un Union créé à partir de deux HList, soit E et F. De ce Union, je voudrais obtenir un nouveau HList avec le type E. Il n'a pas nécessairement la même valeur que la liste initiale, mais je ne veux pas prendre soin, je seulement HList avec le bon typeObtenez un SelectAll de Union dans Shapeless/scala

dans la pratique, ce que je veux pourrait se résumer en une seule fonction: def selectFromUnion[E <: HList, F <: HList](u: Union[E, F]): SelectAll[u.Out, E] = ???

Est-ce que quelqu'un sait comment je peux implémenter cela? Ou si Shapeless a déjà quelque chose à faire?

EDIT: si je peux être plus précis, je veux une preuve qu'une Union de 2 HList contient le type de l'original HList s. Nous pouvons simplifier le problème initial que la recherche de:

implicit def selectFromUnion[E, T <: HList, F <: HList](implicit u: Union[E :: T, F]): Selector[u.Out, E] = ???

Malheureusement, je n'ai toujours pas la moindre idée comment je peux le faire.

+1

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'? –

+0

'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

Répondre

0

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