1 / 26

Listenkomprehension und Typenklassen anhand von Haskell

Listenkomprehension und Typenklassen anhand von Haskell. Proseminar an der TU München Martin Levihn 05.07.2007. Gliederung. Listenkomprehension Einleitung und Motivation Syntax Beispiele und Arbeitsweise mit einem Generator Beispiele und Arbeitsweise mit mehreren Generatoren

auryon
Download Presentation

Listenkomprehension und Typenklassen anhand von Haskell

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Listenkomprehension und Typenklassen anhand von Haskell Proseminar an der TU München Martin Levihn 05.07.2007

  2. Gliederung • Listenkomprehension • Einleitung und Motivation • Syntax • Beispiele und Arbeitsweise mit einem Generator • Beispiele und Arbeitsweise mit mehreren Generatoren • Übersetzung von Listenkomprehension • Typklassen • Begriffserklärung und Einleitung • Deklarationen • Klassendeklaration • Kontext eines Typs • Instanzen deklarieren • Abgeleitete Klassen • Praktische Anwendung • Vergleich zu OOP

  3. Listenkomprehension • Listenkomprehension ähnlich Mengenbeschreibung in der Mathematik • Erstelle Liste als Beschreibung in Bezug auf eine andere Liste • [ x | x <- xs] • „Erstelle die Liste aus allen x, wobei x Element der Liste xs“

  4. Syntax • Allgemein [ Ausdruck | q1, q2, … , qk] • Ausdruck kann beliebige Funktion sein • Qualifikatoren q1 bis qk können sein: • Generator p <- xs, wobei p Variable / Variablen Tupel und xs Listenausdruck • Test, boolscher Ausdruck zum „Auswählen“

  5. Einfache Beispiele (ein Generator) • Verdoppeln jedes Elementes in einer Int Liste double :: [Int] -> [Int] double xs = [ 2*x | x <- xs] Aufruf double [2,3,4] [4,6,8] • Nur die geraden Werte aus einer Int Liste auswählen gerade :: [Int ] -> [ Int] gerade xs = [x | x <- xs, mod x 2 == 0 ] Aufruf gerade [2,3,4] [2,4]

  6. Einfache Beispiele (ein Generator) • map :: (a -> b ) -> [a] -> [b] Funktion rekursiv map f [] = [] map f (x:xs) = f x : map f xs • mit Listkomprehension map f xs = [ f x | x <- xs] • filter :: (a -> Bool) -> [a] -> [a] Funktion rekursiv filter p [] = [] filter p (x:xs) = | p x = x : filter p xs |otherwise = filter p xs • mit Listkomprehension filter p xs = [ x | x <- xs, p x]

  7. Arbeitsweise allgemein (ein Generator) • Format: [f x | x <- xs, p1 x, p2 x , … , pk x] 1) xs wird von links nach rechts durchlaufen 2) ist p1 für x erfüllt, teste p2 … pk a) sind alle „erfüllt“, füge x in Ergebnisliste b) sonst lasse x unberücksichtigt 3) fahre mit nächstem Element fort

  8. Einfache Beispiele (mehrere Generatoren) • Bilde Tupel (x, y) mit x aus xs und y aus ys pairs :: [a] -> [b] -> [(a, b)] pairsxsys= [ (x,y)| x <- xs, y <- ys] Aufruf pairs[1,2,3] [4,5] [(1,4), (1,5), (2,4), (2,5), (3,4), (3,5)] • Bilde pythagoräische Triple pyTriple n :: Int -> [(Int,Int, Int)] pyTriple n = [ (x, y, z) | x <- [2 .. n], y<-[x .. n], z<-[y .. n], x*x+y*y == z*z] AufrufpyTrible 15 [(3,4,5),(5,12,13),(6,8,10),(9,12,15)]

  9. Arbeitsweise Allgemein (mehrere Generatoren) • Format: [ f x | x <- xs, y <- ys , ... z <- zs, p1 , ... pk] • erste Element von xs wird x zugewiesen • für dieses feste x wird das erste y von ys zugewiesen usw. • für diese festen Werte wird z nun von links nach rechts durchlaufen und die Tests werden duchgeführt • es wird der Wert vor dem z erhöht usw. anschaulich: • for (int i1=0; i1<length(xs); i1++){ • for (int i2=0; g1<length(ys); i2++){ • …. • for(int in=0; in<length(zs); in++){ • ….}…}}

  10. Übersetzung von Listenkomprehension • [e | True ] [e] • [e | t, Q] if t then [e | Q] else [] • [e | p<- xs, Q] concatMapfqxs wherefq p = [e | Q] concatMap:: (a -> [b]) -> [a] -> [b] concatMap f [] = [] concatMap f (x:xs) = f x ++ concatMap f xs

  11. Übersetzung von Listenkomprehension • pyTriple n = [ (x, y, z) | x <- [2 .. n], y<-[x .. n], z<-[y .. n], x*x+y*y == z*z] • pyTriple n = concatMap f1 [2 .. n] where f1 x = concatMap f2 [x .. n] where f2 y = concatMap f3 [y .. n] where f3 z = if (x*x + y*y == z*z) then [(x,y,z)] else []

  12. Typenklassen • Polymorphismus • ist, wenn eine Funktion unabhängig von dem Datentyp arbeitet: length :: [a] -> Int length []= 0 length (_:xs) = 1 + length xs • Ad-hoc Polymorphismus • im Sinne von Überladen. Es also für gleichen Operator unterschiedliche Implementierungen gibt (Beispiel + Operator in Java) • Hindley-Milner Typsystem • Typinferenzen werden vom System automatisch erkannt • -> typisiertes Lambda-Kalkühl

  13. Typklassen • Operationen nur auf Typen mit einer gewissen Semantik • Beispiel: elem :: a -> [a] -> Bool elem x [] = False elem x (y:ys) = (x==y) || (elem x ys) • nur möglich wenn == für a definiert • Mittelweg zwischen Polymorphismus und Monomorphismus

  14. Klassendeklaration classEq a where (==) :: a -> a -> Bool • Name der Klasse (Eq) • Signatur der Klasse („fordert“ das (==) implementiert ist) class Name a where ...verlangte Singnatur...

  15. Kontext eines Typs alleQual :: Int -> Int -> Int -> Bool allEqual m n p = (m==n) && (n==p) • keine Beschränkung auf Int sondern auf ==, Verallgemeinerung: alleQual :: Eq a => a -> a -> a -> Bool allEqual m n p = (m==n) && (n==p) • Bereich vor dem => heißt Kontext • „Wenn der Typ a in der Kasse Eq ist, dann hat allEqual den Typ a -> a -> a -> Bool.“

  16. Kontext eines Typs • Liste aus Tupeln soll auf dem ersten Wert sortiert werden und die zweiten Werte sollen ausgegeben werden. • HakellPrelude bietet Klasse Ord, definiert Vergleichsoperatoren, • sowie Visible: class Visible a where toString :: a -> String size :: a -> Int

  17. Kontext eines Typs • geforderte Funktionalität durch Kontext sichergestellt: bSort :: (Ord a, Visible b) => [(a, b)] -> a -> String • Verletzender constraints : nachfolger :: Int -> Int nachfolger = (+1) Aufruf allEqualnachfolgernachfolgernachfolger ERROR: Int -> Int is not an instance of class “Eq”

  18. Instanz einer Klasse • Um einen Typ als Instanz einer Typklasse zu deklarieren, müssen die in der Signatur geforderten Funktionen implementiert werden • Beispiel Bool als Instanz von Eq deklarieren: instanceEqBoolwhere True==True = True False==False = True _ == _ = False

  19. Instanz einer Klasse • Gleichheitstest auf Listen definieren instance Eq[a] where [] == [] = True x:xs == y:ys = x==y && xs==ys _ == _ = False • Ist == definiert?

  20. Instanz einer Klasse • Gleichheitstest nur auf Liste definiert, deren Elemente selbst Instanzen von Eq sind instance Eq a => Eq [a] where [] == [] = True x:xs == y:ys = x==y && xs==ys _ == _ = False • können == als gegeben voraussetzen

  21. Abgeleitete Klassen • Eine Art Vererbung class Eq a => Ord a where (<), (<=), (>), (>=) :: a -> a -> Bool max, min :: a -> a -> Bool compare :: a -> a -> Ordering x <= y = (x < y || x==y) x > y = y < x • Eine Abgeleitete Klasse kann ebenfalls mehrere Basisklassen haben class (Num a, Ord a) => Real a where ...

  22. Praktische Anwendung • data Tag = So | Mo | Di | Mi | Do | Fr | Sa • Um Vergleiche zu machen, deklarieren wir Tag als Instanz von Eq und Ord • Führen Vergleich auf Vergleich von Ints zurück: classEnum a where fromEnum :: a -> Int toEnum :: Int -> a instanceEnum Tag where fromEnum So = 0 fromEnum Mo = 1 fromEnum Di = 2 ... • toEnum analog

  23. Praktische Anwendung instanceEq Tag where (x==y) = (toEnum x == toEnum y) instanceOrd Tag where (x<y) = (toEnum x < toEnum y) • Da dies ein häufiges Vorgehen ist, bietet Haskell dazu die Kurzschreibweise: data Tag = So | Mo | Di | Mi | Do | Fr | Sa deriving (Enum, Eq, Ord) • Instanzen werden automatisch erstellt

  24. Vergleich zu OOP • Gemeinsamkeiten: • Um Instanz zu werden, sind Implementierungen nötig Interfaces in Java oder Basisklassen in C++ • in C++ Default-Implementierungen • Selbstdefinierte Typen können auf Standardoperationen implementiert werden

  25. Vergleich zu OOP • Unterschiede • starke Trennung von Typdeklarationen, Typklassen- und Instanzdeklarationen • Haskell: Klasse ist Sammlung von Typen • C++ : Typen und Klassen synonym • kein Zustand eines Objekts möglich • Kein dynamicbinding möglich • In OOP möglich • show :: ShowType -> String • Bools , Chars wären sub-classes, • [True, 'n', False] ::[ShowType] • In Java sind die implementierten Interfaces/Klassen bei der Klassendefinition anzugeben, bei Haskell späteres Hinzufügen möglich

  26. Literatur • [1] Simon Thompson, 1999. The Craft of Functional Programming, second edition, Addison Wesley Longman, Great Britain • [2] Richard Bird, 1998. Introduction to Functional Programming using Haskell, second edition, Prentice Hallo, Great Britain • [3] The Haskell 98 Report, December 2002, http://www.haskell.org/onlinereport/exps.html#list-comprehensions • [4] D. Rösner, 2007. Einführung in Programmierparadigmen, Univ. Magedburg, http://wdok.cs.uni-magdeburg.de/studium-und-lehre/ lehrveranstaltungen/sommer2007/pgp/slides • [5] Uwe Schmidt, 2002. Abstrakte Datentypen und das Typsystem von Haskell, FH Wedel, http://www.fh-wedel.de/~si/seminare/ss02/Ausarbeitung/2. types/typhas3.html • [6] Peter Padawitz, 2005. Übersetzerbau, Univ. Dortmund http://fldit-www.cs.uni-dortmund.de/~peter/Kapitel1-2.pdf

More Related