Phantom Types Fabian Franzelin Einführung Motivation Haskell Phantom Types Hauptseminar Having Fun With Types Phantom Types Beispiel - Die Peanozahlen Weitere Anwendungsmöglichkeiten C-style printf in Haskell Typrepräsentanten und dynamische Werte Dynamisches Type-checking Fabian Franzelin Technische Universität München 22.06.2011 Zusammenfassung Outline Phantom Types Fabian Franzelin Einführung Einführung Motivation Haskell Motivation Haskell Phantom Types Beispiel - Die Peanozahlen Weitere Anwendungsmöglichkeiten Phantom Types Beispiel - Die Peanozahlen C-style printf in Haskell Typrepräsentanten und dynamische Werte Dynamisches Type-checking Zusammenfassung Weitere Anwendungsmöglichkeiten C-style printf in Haskell Typrepräsentanten und dynamische Werte Dynamisches Type-checking Zusammenfassung Outline Phantom Types Fabian Franzelin Einführung Einführung Motivation Haskell Motivation Haskell Phantom Types Beispiel - Die Peanozahlen Weitere Anwendungsmöglichkeiten Phantom Types Beispiel - Die Peanozahlen C-style printf in Haskell Typrepräsentanten und dynamische Werte Dynamisches Type-checking Zusammenfassung Weitere Anwendungsmöglichkeiten C-style printf in Haskell Typrepräsentanten und dynamische Werte Dynamisches Type-checking Zusammenfassung Motivation - Typen, Werte und Ausdrücke Phantom Types Fabian Franzelin Einführung Motivation Haskell Phantom Types Beispiel - Die Peanozahlen Wert gehört zu Typ Weitere Anwendungsmöglichkeiten C-style printf in Haskell Typrepräsentanten und dynamische Werte Dynamisches Type-checking Zusammenfassung evaluiert zu hat einen Ausdruck Quelle: vgl. Kreiker (2010), S. 2 Motivation - Typen, Werte und Ausdrücke Phantom Types Fabian Franzelin Einführung Motivation Haskell Phantom Types Umsetzung? Wert gehört zu Beispiel - Die Peanozahlen Typ Weitere Anwendungsmöglichkeiten C-style printf in Haskell Typrepräsentanten und dynamische Werte Dynamisches Type-checking Zusammenfassung evaluiert zu hat einen Ausdruck Quelle: vgl. Kreiker (2010), S. 2 Motivation - Typen, Werte und Ausdrücke Phantom Types Fabian Franzelin Einführung Motivation Haskell Phantom Types Umsetzung? Wert gehört zu Beispiel - Die Peanozahlen Typ Weitere Anwendungsmöglichkeiten C-style printf in Haskell Typrepräsentanten und dynamische Werte Dynamisches Type-checking Zusammenfassung Semantik? evaluiert zu hat einen Ausdruck Quelle: vgl. Kreiker (2010), S. 2 Phantom Types Haskell - Einführung Fabian Franzelin Einführung Motivation Typen und Werte Haskell Phantom Types Ein Typ wird zusammen mit den dazugehörigen Werten erstellt mit Hilfe des data Konstrukts Typ Beispiel - Die Peanozahlen Weitere Anwendungsmöglichkeiten C-style printf in Haskell Unterscheidung Typkonstruktor, Wertkonstruktor und Typvariable Typrepräsentanten und dynamische Werte Dynamisches Type-checking gehört zu Beispiel data T a = K1 | K2 a | K3 a a K 1 :: T a K 2 :: a → T a K 3 :: a → a → T a Wert Zusammenfassung Phantom Types Haskell - Einführung Fabian Franzelin Einführung Motivation Typen und Werte Haskell Phantom Types Ein Typ wird zusammen mit den dazugehörigen Werten erstellt mit Hilfe des data Konstrukts Typ Beispiel - Die Peanozahlen Weitere Anwendungsmöglichkeiten C-style printf in Haskell Unterscheidung Typkonstruktor, Wertkonstruktor und Typvariable Typrepräsentanten und dynamische Werte Dynamisches Type-checking gehört zu Beispiel data T a = K1 | K2 a | K3 a a K 1 :: T a K 2 :: a → T a K 3 :: a → a → T a Wert Zusammenfassung Phantom Types Haskell - Einführung Fabian Franzelin Einführung Motivation Typen und Werte Haskell Phantom Types Ein Typ wird zusammen mit den dazugehörigen Werten erstellt mit Hilfe des data Konstrukts Typ Beispiel - Die Peanozahlen Weitere Anwendungsmöglichkeiten C-style printf in Haskell Unterscheidung Typkonstruktor, Wertkonstruktor und Typvariable Typrepräsentanten und dynamische Werte Dynamisches Type-checking gehört zu Beispiel data T a = K1 | K2 a | K3 a a K 1 :: T a K 2 :: a → T a K 3 :: a → a → T a Wert Zusammenfassung Phantom Types Haskell - Einführung Fabian Franzelin Einführung Motivation Typen und Werte Haskell Phantom Types Ein Typ wird zusammen mit den dazugehörigen Werten erstellt mit Hilfe des data Konstrukts Typ Beispiel - Die Peanozahlen Weitere Anwendungsmöglichkeiten C-style printf in Haskell Unterscheidung Typkonstruktor, Wertkonstruktor und Typvariable Typrepräsentanten und dynamische Werte Dynamisches Type-checking gehört zu Beispiel data T a = K1 | K2 a | K3 a a K 1 :: T a K 2 :: a → T a K 3 :: a → a → T a Wert Zusammenfassung Phantom Types Haskell - Einführung cont Fabian Franzelin Einführung Motivation Dynamische Werte Haskell Phantom Types Der Rückgabewert einer Funktion ist dynamisch Wert Beispiel - Die Peanozahlen Weitere Anwendungsmöglichkeiten C-style printf in Haskell Typrepräsentanten und dynamische Werte Beispiele Dynamisches Type-checking (+) :: (Num t ) ⇒ t → t → t evaluiert zu (+) 1 2 = 3 (+) 1.2 3 = 4.2 Ausdruck Zusammenfassung Phantom Types Haskell - Einführung cont Fabian Franzelin Einführung Motivation Statische Typen Haskell Phantom Types Der Rückgabewert einer Funktion hat immer denselben Typ bei gleicher initialer Belegung Typ Beispiel - Die Peanozahlen Weitere Anwendungsmöglichkeiten C-style printf in Haskell Typrepräsentanten und dynamische Werte Dynamisches Type-checking Beispiele hat einen (+) :: (Num t ) ⇒ t → t → t (+) 1 2 = 3 :: (Num t ) ⇒ t (+) 1.2 3 = 4.2 :: (Fractional t ) ⇒ t Ausdruck Zusammenfassung Herausforderung Phantom Types Fabian Franzelin Einführung Motivation Haskell Phantom Types Beispiel - Die Peanozahlen Ziel Weitere Anwendungsmöglichkeiten C-style printf in Haskell Dynamische Typisierung mit generischer Programmierung im Kontext einer statisch typisierten Umgebung einfach zu ermöglichen. Typrepräsentanten und dynamische Werte Dynamisches Type-checking Zusammenfassung Outline Phantom Types Fabian Franzelin Einführung Einführung Motivation Haskell Motivation Haskell Phantom Types Beispiel - Die Peanozahlen Weitere Anwendungsmöglichkeiten Phantom Types Beispiel - Die Peanozahlen C-style printf in Haskell Typrepräsentanten und dynamische Werte Dynamisches Type-checking Zusammenfassung Weitere Anwendungsmöglichkeiten C-style printf in Haskell Typrepräsentanten und dynamische Werte Dynamisches Type-checking Zusammenfassung Beispiel - Die Peanozahlen Definition Phantom Types Fabian Franzelin Einführung Motivation Die Peanozahlen definieren die Menge der natürlichen Zahlen: Haskell Phantom Types 0∈N Beispiel - Die Peanozahlen n ∈ N ⇒ n − 1 ∈ N für n > 0 Weitere Anwendungsmöglichkeiten C-style printf in Haskell Semantik: Peanozahlen mit If-Abfrage Typrepräsentanten und dynamische Werte Dynamisches Type-checking Zusammenfassung Zero :: Term Int Succ :: Term Int → Term Int Pred :: Term Int → Term Int IsZero :: ∀t .Term t → Term Bool If :: ∀t .Term Bool → Term t → Term t → Term t Beispiel - Die Peanozahlen Implementierung Phantom Types Fabian Franzelin Einführung Motivation Haskell Phantom Types data Term t where Beispiel - Die Peanozahlen Zero :: (t ~ Int) => Term Int Succ :: (t ~ Int) => (Term Int) -> Term Int Pred :: (t ~ Int) => (Term Int) -> Term Int Weitere Anwendungsmöglichkeiten C-style printf in Haskell Typrepräsentanten und dynamische Werte Dynamisches Type-checking IsZero :: (t ~ Bool) => (Term Int) -> Term Bool If :: (t ~ a) => (Term Bool) -> (Term a) -> (Term a) -> Term a Zusammenfassung Beispiel - Die Peanozahlen → Pantom Types Implementierung Phantom Types Fabian Franzelin Einführung Motivation Haskell Phantom Types data Term t where Beispiel - Die Peanozahlen Zero :: (t ~ Int) => Term Int Succ :: (t ~ Int) => (Term Int) -> Term Int Pred :: (t ~ Int) => (Term Int) -> Term Int Weitere Anwendungsmöglichkeiten C-style printf in Haskell Typrepräsentanten und dynamische Werte Dynamisches Type-checking IsZero :: (t ~ Bool) => (Term Int) -> Term Bool If :: (t ~ a) => (Term Bool) -> (Term a) -> (Term a) -> Term a Definition Als Phantom Types werden parametrisierte Typen bezeichnet, die ihre Typargumente nicht verwenden [Cheney, Hinze (2003)] Zusammenfassung Beispiel - Die Evaluierungsfunktion Implementierung Phantom Types Fabian Franzelin Einführung Motivation Haskell eval :: ∀t .Term t → t Phantom Types Beispiel - Die Peanozahlen Weitere Anwendungsmöglichkeiten eval Zero = 0 C-style printf in Haskell eval (Succ a) = eval a + 1 eval (Pred a) = eval a - 1 Typrepräsentanten und dynamische Werte Dynamisches Type-checking Zusammenfassung eval (IsZero a) = eval a == 0 eval (If a b c) = if eval a then eval b else eval c Beispiele eval (Succ (Succ Zero)) ⇒ 2 eval (IsZero (Succ Zero)) ⇒ False eval (If (IsZero Zero) (Succ Zero) Zero) ⇒ 1 Outline Phantom Types Fabian Franzelin Einführung Einführung Motivation Haskell Motivation Haskell Phantom Types Beispiel - Die Peanozahlen Weitere Anwendungsmöglichkeiten Phantom Types Beispiel - Die Peanozahlen C-style printf in Haskell Typrepräsentanten und dynamische Werte Dynamisches Type-checking Zusammenfassung Weitere Anwendungsmöglichkeiten C-style printf in Haskell Typrepräsentanten und dynamische Werte Dynamisches Type-checking Zusammenfassung C-style printf Funktionssignatur Phantom Types Fabian Franzelin Einführung Motivation Haskell Phantom Types int printf (const char* format, . . . ) Beispiel - Die Peanozahlen Weitere Anwendungsmöglichkeiten C-style printf in Haskell printf ist eine Ausgabefunktion in C Typrepräsentanten und dynamische Werte Dynamisches Type-checking Der Eingabestring beinhaltet normalen Text und spezielle Tags Die Tags markieren den Typ des Wertes, der an der entsprechenden Stelle in die Ausgabe übernommen werden soll Diese Werte werden als weitere Parameter an printf übergeben Zusammenfassung C-style printf cont Beispiele Phantom Types Fabian Franzelin Einführung Motivation Haskell printf(“Hallo, mein Name ist %s”, “Fabian”); ⇒ “Hallo, mein Name ist Fabian” printf(“Ich b%cn %d Jahre und %i Stunden alt”, ’i’, 27, 12.12); ⇒ “Ich bin 23 Jahre und -1546188227 Stunden alt” Schwierigkeiten 1 Unendliche Menge an Eingabeparametern notwendig, die allesamt unterschiedlichen Typs sein können 2 Dynamisches Type-checking und Casting Phantom Types Beispiel - Die Peanozahlen Weitere Anwendungsmöglichkeiten C-style printf in Haskell Typrepräsentanten und dynamische Werte Dynamisches Type-checking Zusammenfassung Phantom Types (1) Typrepräsentanten Fabian Franzelin Man definiert sich Typrepräsentanten als Phantom Type, die stellvertretend für jeweils einen Tag stehen, der über printf ausgegeben werden kann Einführung Motivation Haskell Phantom Types Beispiel - Die Peanozahlen Tag Repräsentant Typ %i RInt Int %c RChar Char %l RList ∀a. [a] %t RPair ∀a, b. (a, b) Weitere Anwendungsmöglichkeiten C-style printf in Haskell Typrepräsentanten und dynamische Werte Dynamisches Type-checking Man definiert sich einen Typ der Werte mit dem dazugehörigen Typrepräsentant kapselt Dynamic :: Typrepr äsentant → Wert → Dynamic Zusammenfassung (1) Typrepräsentanten cont Implementierung der Typrepräsentanten Phantom Types Fabian Franzelin Einführung Motivation Haskell data Type t where RInt Phantom Types :: (t ~ Int) => Type Int RChar :: (t ~ Char) => Type Char RList :: (t ~ [a]) => (Type a) -> Type [a] Beispiel - Die Peanozahlen Weitere Anwendungsmöglichkeiten C-style printf in Haskell Typrepräsentanten und dynamische Werte RPair :: (t ~ (a, b)) => (Type a) -> (Type b) -> Type (a, b) RDyn :: Type Dynamic data Dynamic where Dyn :: Type t -> t -> Dynamic Hinweis Man beachte die zirkuläre Definition von Type t und Dynamic Dynamisches Type-checking Zusammenfassung (1) Liste dynamischer Werte Eine Liste von Dynamics kann nun als unendliche Parameterliste für printf verwendet werden Phantom Types Fabian Franzelin Einführung Motivation Haskell Phantom Types Beispiele [Dyn RChar ’a’, Dyn (RList RChar) “Fabian”] [Dyn RInt 27, Dyn (RPair RInt RChar) (1, ’a’)] Beispiel - Die Peanozahlen Weitere Anwendungsmöglichkeiten C-style printf in Haskell Typrepräsentanten und dynamische Werte Dynamisches Type-checking Zusammenfassung Die Funktionssignatur lässt sich nun ähnlich zur C-Funktion angeben Haskell Funktionssignatur für printf printf :: String → [Dynamic ] → Maybe String (2) Dynamisches Type-checking Ein bestimmter Tag erwartet einen Wert eines bestimmten Typs Es muss zur Laufzeit sichergestellt werden, dass auch der geforderte Typ vorliegt ⇒ Type-checking Die tequal Funktion Phantom Types Fabian Franzelin Einführung Motivation Haskell Phantom Types Beispiel - Die Peanozahlen Weitere Anwendungsmöglichkeiten C-style printf in Haskell Typrepräsentanten und dynamische Werte tequal :: Type t → Type v → Maybe (t → v ) Dynamisches Type-checking Zusammenfassung Beispiele tequal RInt RInt ⇒ Just id tequal (RList RChar) (RList RInt) ⇒ Nothing (2) Casting Im zweiten Schritt muss bei erfolgreichem Type-checking der dynamischen Wert in den erwarteten Typ gecastet werden Phantom Types Fabian Franzelin Einführung Motivation Haskell Phantom Types Beispiel - Die Peanozahlen Die cast Funktion Weitere Anwendungsmöglichkeiten C-style printf in Haskell cast :: ∀t .Dynamic → Type t → Maybe t Typrepräsentanten und dynamische Werte Dynamisches Type-checking cast (Dyn ra a) rb = fmap (\f -> f a) (tequal ra rb) Beispiele cast (Dyn RInt 27) RInt ⇒ Just 27 cast (Dyn (RList RChar) “Fabian”) (RList RInt) ⇒ Nothing Zusammenfassung C-Style printf in Haskell Letzter Schritt: String parsen und Tags erkennen Phantom Types Fabian Franzelin Einführung Motivation Haskell Beispiele Phantom Types Beispiel - Die Peanozahlen printf “Hallo, mein Name ist %s” [Dyn (RList Char) “Fabian”] ⇒ “Hallo, mein Name ist Fabian” Weitere Anwendungsmöglichkeiten printf “Ich bin %d Jahre alt” [Dyn RInt 27] ⇒ “Nothing” Zusammenfassung C-style printf in Haskell Typrepräsentanten und dynamische Werte Dynamisches Type-checking Outline Phantom Types Fabian Franzelin Einführung Einführung Motivation Haskell Motivation Haskell Phantom Types Beispiel - Die Peanozahlen Weitere Anwendungsmöglichkeiten Phantom Types Beispiel - Die Peanozahlen C-style printf in Haskell Typrepräsentanten und dynamische Werte Dynamisches Type-checking Zusammenfassung Weitere Anwendungsmöglichkeiten C-style printf in Haskell Typrepräsentanten und dynamische Werte Dynamisches Type-checking Zusammenfassung Zusammenfassung Unterschied zwischen dynamischer und statischer Typisierung Dynamische Typisierung in statisch typisiertem System integriert unter der Verwendung von Phantom Types ohne eine Beeinträchtigung der Korrektheitseigenschaft möglich Vorgestellte Anwendungsbeispiele: Einfache Ausdruckssprache mit Evaluierungsfunktion eval Typrepräsentanten und dynamischen Werten mit beispielhafter printf Implementierung Weiteres Anwendungsbeispiel: Universelle Traversierungsfunktion über Phantom Types Phantom Types Fabian Franzelin Einführung Motivation Haskell Phantom Types Beispiel - Die Peanozahlen Weitere Anwendungsmöglichkeiten C-style printf in Haskell Typrepräsentanten und dynamische Werte Dynamisches Type-checking Zusammenfassung Literaturverzeichnis James Cheney and Ralf Hinze. A lightweight implementation of generics and dynamics. In Proceedings of the 2002 ACM SIGPLAN Haskell Workshop, pages 90–104. ACM-Press, Oktober 2002. Phantom Types Fabian Franzelin Einführung Motivation Haskell James Cheney and Ralf Hinze. Phantom types. Technical report, Cornell University, May 2003. Phantom Types Ralf Hinze. Fun with phantom types. http://www.comlab.ox.ac.uk/people/ralf.hinze/talks/FOP.pdf, März 2003. Weitere Anwendungsmöglichkeiten Beispiel - Die Peanozahlen C-style printf in Haskell Richard B. Kieburtz. Automated soundness checking of a programming logic for haskell. programatica.cs.pdx.edu/P/kieburtz.pdf, 2002. Jörg Kreiker. Vorlesung: Programming languages. Technische Unversität München, 2010/2011. Daan Leijen and Erik Meijer. Domain-specific embedded compilers. In Proceedings of the 2nd Conference on Domain-Specific-Languages, pages 109–122, Oktober 1999. Mark Shields and Simon Peyton Jones. Object-oriented style overloading for haskell, 2001. Typrepräsentanten und dynamische Werte Dynamisches Type-checking Zusammenfassung