2010-10-30 7 views
9

Angenommen, definieren wir einen GADT zum Vergleich von Typen:Runtime Vergleich von Typen für das Anheben polymorphe Datenstrukturen in GADTs

data EQT a b where 
    Witness :: EQT a a 

Ist es dann möglich, eine Funktion EQT mit folgenden Art Unterschrift zu erklären:

eqt :: (Typeable a, Typeable b) => a -> b -> Maybe (EQT a b) 

... so dass EQT xy zu gerade Zeuge wertet wenn typeOf x == t ypeOf y --- und sonst zu Nichts? Die Funktion eqt würde es ermöglichen, gewöhnliche polymorphe Datenstrukturen in GADTs zu heben.

Antwort

11

Ja ist es. Hier ist eine Möglichkeit:

Zuerst der Gleichheitstyp.

data EQ :: * -> * -> * where 
    Refl :: EQ a a -- is an old traditional name for this constructor 
    deriving Typeable 

Beachten Sie, dass es selbst eine Instanz von Typable gemacht werden kann. Das ist der Schlüssel. Jetzt muss ich nur die Refl, die ich brauche, in die Hände bekommen.

refl :: a -> EQ a a 
refl _ = Refl 

Und jetzt kann ich versuchen zu drehen (Refl :: Eq a a) in etwas vom Typ (Eq a b) von Data.Typeable dem Darsteller Operator. Das funktioniert nur, wenn a und b gleich sind!

eq :: (Typeable a, Typeable b) => a -> b -> Maybe (EQ a b) 
eq a _ = cast (refl a) 

Die harte Arbeit wurde bereits getan.

Weitere Variationen zu diesem Thema finden Sie in der Data.Witness-Bibliothek, , aber der Operator "Data.Typeable" ist für diesen Job ausreichend. Es ist Betrug, natürlich, aber sicher verpackt Betrug.

+0

Das ist ordentlich! Vielen Dank. –

+0

Sicher verpackt, solange niemand eine falsche "Data.Typeable" -Instanz auf etwas gemacht hat. ('Ableiten von Typable' ist immer sicher.) –

+0

Beachten Sie, dass diese Tage' eq' im 'Data.Typeable' Modul als [' eqT' verfügbar sind (https://hackage.haskell.org/package/base-4.9) .0.0/docs/Daten-Typable.html # v: eqT) –