2014-06-14 12 views
13

Questo tipo di dati può avere type role HCons' representational representational, che consente di utilizzare coerce per aggiungere o rimuovere i newtypes applicati agli elementi, senza la necessità di attraversare l'elenco.questo GADT ha effettivamente il ruolo di tipo rappresentativo

data HNil' = HNil' 
data HCons' a b = HCons' a b 

Tuttavia la sintassi per tali elenchi non è così bello come quelli con il seguente GADT

data HList (l::[*]) where 
    HNil :: HList '[] 
    HCons :: e -> HList l -> HList (e ': l) 

Ho una classe di convert between these two representations, in modo tale che Prime (HList [a,b]) ~ HCons' a (HCons' b HNil'). Quella lezione rende

coerceHList :: Coercible (Prime a) (Prime b) => HList a -> HList b 
coerceHList = unsafeCoerce 

sicuro?

+0

FWIW, si, penso di si. Ma non conosco abbastanza gli interni dei ruoli per fare un argomento convincente. Il tuo esempio sembra essere un altro caso in cui l'attuale sistema di ruolo non è abbastanza espressivo. – kosmikus

risposta

2

Non credo che l'esistenza di una conversione da sola sia sufficiente. Ad esempio, il seguente mi consente anche di convertire tra un GADT e un paio coercibile di tipi, ma di certo non sarebbe sicuro di costringere direttamente il GADT:

newtype Age = Age Int 

data Foo a where 
    I :: Bool -> Int -> Foo Int 
    A :: Age -> Bool -> Foo Age 

class ConvFoo a where 
    toFoo :: (Bool, a) -> Foo a 
    fromFoo :: Foo a -> (Bool, a) 

instance ConvFoo Int where 
    toFoo (b, i) = I b i 
    fromFoo (I b i) = (b, i) 

instance ConvFoo Age where 
    toFoo (b, a) = A a b 
    fromFoo (A a b) = (b, a) 

potrei anche definire banalmente una funzione di tipo simile UnFoo a Prime.

penso che la differenza fondamentale tra i due esempi è che nella mia, Age e Int hanno la stessa rappresentazione, mentre nel vostro '[] e e':l non hanno la stessa rappresentazione.

Quindi c'è ancora un caso di dire, come lei suggerisce il titolo, che l ha tipo di ruolo rappresentativo, perché è una specie di ovvio che HList l1 e HList l2 avere le stesse rappresentazioni se l1 e l2 hanno le stesse rappresentazioni.

Tuttavia, poiché in teoria le rappresentazioni dipendono dall'implementazione, non penso che si possa mai considerare questo assolutamente sicuro finché GHC non lo accetta direttamente.

+0

Non ne sono così sicuro "è ovvio che HList l1 e HList l2 abbiano le stesse rappresentazioni se l1 e l2 hanno le stesse rappresentazioni". Potremmo scrivere 'HCons :: (el ~ (e ': l)) => e -> HList l -> HList el'. Quindi è possibile che ghc memorizzi qualcosa per 'el ~ (e ': l)' che fa riferimento ai tipi 'e, el, l' originali, e non a quelli che sono attualmente nel costruttore? – aavogt

+0

Anche allora, ogni 'HCon' avrebbe ancora la stessa rappresentazione di superficie di ogni altro 'HCon', no? Quindi se 'e' e' HList l' hanno anche le stesse rappresentazioni, allora l'intero 'HCons' lo farebbe. –

+0

Penso che il punto chiave sia che '':' e '' []' sono tipi concreti che devono essere diversi, quindi non c'è il rischio di confondere 'HCons' e' HNil'. Non sono affatto sicuro di come formulare la condizione proprio però! –

Problemi correlati