2015-09-03 20 views
8

Zasadniczo szukam przeciwieństwa do klasy typu Prepend[A, B].Dzielenie listy HList połączonej za pomocą polecenia Przygotuj [A, B]

Jeśli mam coś takiego:

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 

Mam HLista typu A i HListb typu B mogę znaleźć prepend: Prepend[A, B] takie, że mogę łączyć je z a ++ b.

Ale jeśli mam HListab typu prepend.Out, w jaki sposób można wyodrębnić oryginalne A i B? Nie mogę znaleźć klasy, która wykonuje tę pracę i być może nie ma takiej. Wygląda na to, że potrzebowałbym czegoś takiego, jak trait Cut[A <: HList, B <: HList, c <: HList], który był świadkiem, że C został utworzony przez oczekujące A na B, chociaż nie jestem pewien, w jaki sposób chciałbym wygenerować świadków.

grubsza tak:

def Cut[A <: HList, B <: HList, C <: HList](c: C)(implicit cut: Cut[A, B, C]): (A, B) = ??? 
+0

możesz rozważyć [tagowanie] (http://eed3si9n.com/learning-scalaz/Tagged+type.html) (ostrzeżenie: typy oznaczone skalą nie są tak fajne, jak były) każdego elementu z unikalnym typem (generuj go jako zależny od ścieżki), jak znacznik 'val a: A =" a ":: 1 :: HNil; val a: B = "a" :: 1 :: HNil tagged', a następnie po prostu filtruj każdą listę według typu. tylko pomysł - nie sprawdziłem :) – dk14

Odpowiedz

5

Można to zrobić dość wprost z 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] 

, a następnie:

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 "cofnąć" operacji dla Remove typ klasy i może mieć sens mieć som ething podobny wbudowany w Prepend.

Powiązane problemy