2014-06-14 3 views
13

Dieser Datentyp kann type role HCons' representational representational, die Verwendung von coerce ermöglicht Hinzufügen oder Entfernen von newtypes auf die Elemente angewendet, ohne die Liste durchlaufen müssen.hat diese GADT tatsächlich Typ representational

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

jedoch die Syntax für diese Listen ist nicht so schön wie die mit der folgenden GADT

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

ich eine Klasse zu convert between these two representations habe, so dass Prime (HList [a,b]) ~ HCons' a (HCons' b HNil'). Macht diese Klasse

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

sicher?

+0

FWIW, ja, ich denke schon. Aber ich weiß nicht genug über das Innere von Rollen, um tatsächlich ein überzeugendes Argument zu liefern. Ihr Beispiel scheint ein weiterer Fall zu sein, in dem das derzeitige Rollensystem nicht sehr ausdrucksvoll genug ist. – kosmikus

Antwort

2

Ich glaube nicht, dass die Existenz einer Konvertierung allein ausreicht. Zum Beispiel läßt mich folgende auch zwischen einem GADT und einem coercible Paar Typen konvertieren, aber es wäre sicherlich nicht sicher sein, um direkt die GADT coerce:

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) 

ich auch eine UnFoo Typ Funktion trivialen definieren könnte ähnlich zu Prime.

Ich denke, der wesentliche Unterschied zwischen den beiden Beispielen ist, dass in dir, Age und Int nicht die gleiche Darstellung haben, während in Ihren '[] und e':l nicht die gleiche Darstellung haben.

So gibt es immer noch einen Fall zu sagen, wie Sie in dem Titel vorschlagen, dass l geben Rolle gegenständlich hat, weil es ziemlich offensichtlich ist, dass HList l1 und HList l2 die gleichen Vorstellungen haben, wenn l1 und l2 die gleichen Vorstellungen haben.

Da jedoch die Darstellungen in der Theorie implementierungsabhängig sind, glaube ich nicht, dass Sie dies jemals als absolut sicher betrachten können, bis GHC es direkt akzeptiert.

+0

Ich bin nicht so sicher über "es ist irgendwie offensichtlich, dass HList l1 und HList l2 die gleichen Darstellungen haben, wenn l1 und l2 die gleichen Darstellungen haben". Wir könnten 'HCons :: (el ~ (e ': 1)) => e -> HList 1 -> HList el' schreiben. Dann ist es möglich, dass ghc etwas für 'el ~ (e ': l)' speichert, das auf die ursprünglichen 'e, el, l' Typen verweist und nicht auf die, die sich gerade im Konstruktor befinden? – aavogt

+0

Selbst dann hätte jedes 'HCons' immer noch die gleiche Oberflächenrepräsentation wie jedes andere' HCons', oder nicht? Wenn also "e" und "HList l" auch die gleichen Darstellungen hätten, dann würden die ganzen 'HCons'. –

+0

Ich denke, der entscheidende Punkt ist, dass ":" und "[]" konkrete Typen sind, die unterschiedlich sein müssen, so dass es kein Risiko gibt, "HCons" und "HNil" zu verwechseln. Ich bin mir aber überhaupt nicht sicher, wie ich den Zustand genau formulieren soll! –

Verwandte Themen