2014-11-05 7 views
7

Supponendo che abbiamo un tipo T[A,B], possiamo esprimere il seguente tipo di vincolo, chiamiamolo HT:astrazione su una sequenza di tipi

ogni tipo soddisfacente HT devono essere di forma T[P1, P2] :: T[P2, P3] :: T[P3, P4] :: ... :: T[PN-1, PN] :: HNil

per qualche type x = P1 :: P2 :: ... :: PN :: HNil.

Sto cercando di trovare un'astrazione su una pipeline di elaborazione sequenziale digitata.

+0

Solo pensando ad alta voce, ma forse dovresti modellare i tubi in modo esplicito e non solo i passaggi di elaborazione. Perché i tubi hanno lo stesso tipo a "fine" ... –

+0

Ereditarietà? Tutte le tue classi P1, P2, ... PN potrebbero ereditare dalla stessa super classe in modo da utilizzare T [PSUPER, PSUPER] –

+0

@rspencer, presumo che l'OP voglia sapere che il secondo parametro tipo del tipo di uno l'elemento list è dello stesso tipo del primo parametro type del tipo dell'elemento successivo della lista. Non solo che sono tutti T [Px, Py] per alcuni xey. –

risposta

6

Il modo più conveniente per fare questo genere di cose è di solito scrivere la propria classe di tipo. Ecco un rapido schizzo di lavoro:

import shapeless._ 

trait T[I, O] extends (I => O) 

trait Pipeline[P <: HList] { 
    type In 
    type Out 
    type Values <: HList 
} 

object Pipeline { 
    type Aux[P <: HList, In0, Out0, Values0 <: HList] = Pipeline[P] { 
    type In = In0; type Out = Out0; type Values = Values0 
    } 

    def apply[P <: HList](
    implicit pipeline: Pipeline[P] 
): Aux[P, pipeline.In, pipeline.Out, pipeline.Values] = pipeline 

    implicit def onePipeline[I, O]: Aux[T[I, O] :: HNil, I, O, I :: O :: HNil] = 
    new Pipeline[T[I, O] :: HNil] { 
     type In = I 
     type Out = O 
     type Values = I :: O :: HNil 
    } 

    implicit def longerPipeline[I, O, P <: HList, Out0, Values0 <: HList](
    implicit pipeline: Aux[P, O, Out0, Values0] 
): Aux[T[I, O] :: P, I, Out0, I :: Values0] = 
    new Pipeline[T[I, O] :: P] { 
     type In = I 
     type Out = Out0 
     type Values = I :: Values0 
    } 
} 

E poi (riformattato per chiarezza):

scala> Pipeline[T[String, Int] :: T[Int, Char] :: HNil] 
res5: Pipeline[T[String, Int] :: T[Int, Char] :: HNil] { 
    type In = String 
    type Out = Char 
    type Values = String :: Int :: Char :: HNil 
} = [email protected] 

scala> Pipeline[T[String, Int] :: T[Char, Char] :: HNil] 
<console>:19: error: could not find implicit value for parameter 
    pipeline: Pipeline[[T[String, Int] :: T[Char, Char] :: HNil] 
       Pipeline[T[String, Int] :: T[Char, Char] :: HNil] 
        ^

Il gasdotto non valida non si compila, e per la valida otteniamo gli endpoint ei valori intermedi correttamente dedotto .

+0

Grazie, è esattamente quello che stavo cercando. – ponythewhite