diff options
| author | Gregor Kleen <gkleen@yggdrasil.li> | 2015-11-03 10:41:00 +0100 |
|---|---|---|
| committer | Gregor Kleen <gkleen@yggdrasil.li> | 2015-11-03 10:41:00 +0100 |
| commit | bbe07c6bd087db4e8319e249380a1823f2b387f1 (patch) | |
| tree | e345ca037081f24381bc29873f4d2796273e4075 | |
| parent | 593b035e5e40aa3255b364c5eb29a96917a69032 (diff) | |
| download | uni-bbe07c6bd087db4e8319e249380a1823f2b387f1.tar uni-bbe07c6bd087db4e8319e249380a1823f2b387f1.tar.gz uni-bbe07c6bd087db4e8319e249380a1823f2b387f1.tar.bz2 uni-bbe07c6bd087db4e8319e249380a1823f2b387f1.tar.xz uni-bbe07c6bd087db4e8319e249380a1823f2b387f1.zip | |
FFP Blatt 03
| -rw-r--r-- | ws2015/FFP/blaetter/03/FFP_U03_Funktoren.hs | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/ws2015/FFP/blaetter/03/FFP_U03_Funktoren.hs b/ws2015/FFP/blaetter/03/FFP_U03_Funktoren.hs new file mode 100644 index 0000000..51ab9e5 --- /dev/null +++ b/ws2015/FFP/blaetter/03/FFP_U03_Funktoren.hs | |||
| @@ -0,0 +1,186 @@ | |||
| 1 | -- Fortgeschrittene Funktionale Programmierung, | ||
| 2 | -- LMU, TCS, Wintersemester 2015/16 | ||
| 3 | -- Steffen Jost, Alexander Isenko | ||
| 4 | -- | ||
| 5 | -- Übungsblatt 03 am 3.11.2015 | ||
| 6 | -- | ||
| 7 | -- Thema: | ||
| 8 | -- | ||
| 9 | -- Anweisung: | ||
| 10 | -- Gehen Sie diese Datei durch und bearbeiten Sie | ||
| 11 | -- alle Vorkommen von undefined bzw. die mit -- !!! TODO !!! | ||
| 12 | -- markierten Stellen. Testen Sie Ihre Lösungen mit GHCi! | ||
| 13 | -- | ||
| 14 | -- | ||
| 15 | |||
| 16 | import Data.List (groupBy) | ||
| 17 | import Data.Function (on) | ||
| 18 | |||
| 19 | -- Bearbeiten Sie zuerst Übungsblatt 02 vollständig! | ||
| 20 | |||
| 21 | |||
| 22 | ---- A3-1 Funktoren | ||
| 23 | -- | ||
| 24 | -- Machen Sie folgende Datentypen zur einer Instanz der Klasse Functor. | ||
| 25 | -- Versuchen Sie dabei, möglichst nicht in die Folien zu schauen! | ||
| 26 | -- (Falls Sie doch in die Folien schauen, dann möglichst nur 2-25 und 2-31ff.; | ||
| 27 | -- da die Beispiele 2-28 und 2-29 nahezu die komplette Lösung verraten.) | ||
| 28 | |||
| 29 | |||
| 30 | -- a) | ||
| 31 | data Options a = None | One a | Two a a | Three a a a | ||
| 32 | deriving (Ord, Show) | ||
| 33 | |||
| 34 | -- Wenn wir nur die ersten beiden Konstuktoren von "Options" betrachten, | ||
| 35 | -- dann haben wir genau den Datentyp "Maybe" aus der Standardbibliothek. | ||
| 36 | |||
| 37 | instance Functor Options where | ||
| 38 | fmap _ None = None | ||
| 39 | fmap f (One a) = One (f a) | ||
| 40 | fmap f (Two a b) = Two (f a) (f b) | ||
| 41 | fmap f (Three a b c) = Three (f a) (f b) (f c) | ||
| 42 | |||
| 43 | -- Zum Testen: | ||
| 44 | testO0 = None | ||
| 45 | testO1 = One 4.2 | ||
| 46 | testO2 = Two 4.2 6.9 | ||
| 47 | -- Tests auskommentierbar, sobald Functor Instanz definiert: | ||
| 48 | testa1 = None == fmap (+2) testO0 | ||
| 49 | testa2 = Two 8.4 13.8 == fmap (*2) testO2 | ||
| 50 | |||
| 51 | |||
| 52 | -- b) | ||
| 53 | data Tree a = Node a [Tree a] | ||
| 54 | deriving (Eq, Show) | ||
| 55 | |||
| 56 | --Hilfsfunktion | ||
| 57 | leaf :: a -> Tree a | ||
| 58 | leaf x = Node x [] | ||
| 59 | |||
| 60 | instance Functor Tree where | ||
| 61 | fmap f (Node a xs) = Node (f a) $ map (fmap f) xs | ||
| 62 | |||
| 63 | -- Zum Testen: | ||
| 64 | testT1 = Node 1 [Node 2 [Node 3 [], leaf 4, Node 5 [leaf 6, leaf 7, leaf 8]], leaf 9, Node 10 [leaf 11]] | ||
| 65 | testT2 = Node False [Node True [Node False [],leaf True,Node False [leaf True,leaf False,leaf True]],leaf False,Node True [leaf False]] | ||
| 66 | -- Test auskommentierbar, sobald Functor Instanz definiert: | ||
| 67 | testb1 = testT2 == (fmap even testT1) | ||
| 68 | |||
| 69 | |||
| 70 | |||
| 71 | |||
| 72 | ---- A3-2 Funktor (->) a | ||
| 73 | -- | ||
| 74 | -- Die Standardbibliothek definiert eine Funktor-Instanz für den Typ "(->) a". | ||
| 75 | -- Wir wollen hier herausfinden, was dies bedeutet: | ||
| 76 | -- | ||
| 77 | -- Der Typ "(->) a" ist ein Typ mit einem ``Loch'', | ||
| 78 | -- so wie die Typen "Tree" oder "[ ]" auch. | ||
| 79 | -- Die runde Klammer bedeutet lediglich Präfix-Notation anstatt Infix-Notation. | ||
| 80 | -- Wenn wir also einen Typ "b" hineingeben wird daraus der Typ (im vertrauten Infix) | ||
| 81 | -- a -> b | ||
| 82 | -- ganz analog wird aus "Tree" oder "[ ]" zu "Tree b" oder "[b]". | ||
| 83 | -- | ||
| 84 | |||
| 85 | -- a) Welchen konkreten Typ bekommt die Funktion "fmap" | ||
| 86 | -- für die Funktor-Instanz von "(->) a"? | ||
| 87 | -- | ||
| 88 | -- Hinweis: Ein Beispiel findet sich auf Folie 2-26. | ||
| 89 | -- Oben ist der allgemeine Typ von fmap angegeben. | ||
| 90 | -- Unten dann nochmal konkreter für die Listen-Instanz. | ||
| 91 | |||
| 92 | {- | ||
| 93 | fmap :: Functor f => (a -> b) -> f a -> f b | ||
| 94 | fmap :: (a -> b) -> (x -> a) -> (x -> b) | ||
| 95 | -} | ||
| 96 | |||
| 97 | -- b) Die Standardbibliothek enthält bereits eine Funktion des in a) gefundenen Typs! | ||
| 98 | -- Wie heisst diese Funktion und was macht sie? | ||
| 99 | -- Testen Sie anschließend in GHCI, ob sie die Funktion | ||
| 100 | -- tatsächlich mit fmap vertauschen können! | ||
| 101 | -- | ||
| 102 | -- Hinweis: Diese Funktion wird Ihnen in einer Vorlesung über | ||
| 103 | -- funktionaler Programmierung mit Sicherheit begegnet sein, | ||
| 104 | -- da sie von fundamentaler Bedeutung ist. | ||
| 105 | -- (Jedoch sicherlich nicht als Funktor behandelt... ;) ) | ||
| 106 | |||
| 107 | {- | ||
| 108 | fmap ist hier identisch zu (.) | ||
| 109 | λ ((\a -> (a, a)) `fmap` (\i -> i + 2)) 2 | ||
| 110 | (4,4) | ||
| 111 | -} | ||
| 112 | |||
| 113 | |||
| 114 | |||
| 115 | |||
| 116 | ---- A3-3 Unendliche Listen | ||
| 117 | -- | ||
| 118 | -- a) Definieren Sie die unendliche Liste alle Zweierpotenzen: [1,2,4,8,16,32,64,128,256,..] | ||
| 119 | |||
| 120 | quadrate :: [Integer] | ||
| 121 | quadrate = map (2^) [0..] | ||
| 122 | |||
| 123 | -- Zum Testen: | ||
| 124 | q1 = take 5 quadrate | ||
| 125 | -- > q1 | ||
| 126 | -- [1,2,4,8,16] | ||
| 127 | q2 = quadrate !! 10 | ||
| 128 | -- > q2 | ||
| 129 | -- 1024 | ||
| 130 | |||
| 131 | |||
| 132 | -- b) Definieren Sie eine unendliche Liste, welche alle | ||
| 133 | -- erdenklichen Strings aus den Buchstaben ['a','b','c','d']. | ||
| 134 | -- Die Reihenfolge ist relativ egal, aber kürzere Strings sollen vor längeren Erscheinen; | ||
| 135 | -- d.h. "dd" kommt nach "b", aber vor "abc" | ||
| 136 | |||
| 137 | alleVariablen :: [String] | ||
| 138 | alleVariablen = seed : alleVariablen' [seed] | ||
| 139 | where | ||
| 140 | seed = "" | ||
| 141 | vars = ['a','b','c','d'] | ||
| 142 | alleVariablen' prevs = now ++ alleVariablen' now | ||
| 143 | where | ||
| 144 | now = [v : p | v <- vars, p <- prevs] | ||
| 145 | |||
| 146 | -- Zum Testen: | ||
| 147 | check l x = (map length . groupBy ((==) `on` length)) (take x l) | ||
| 148 | |||
| 149 | -- Beispielimplementierung (muss nicht identisch sein): | ||
| 150 | -- > take 30 alleVariablen | ||
| 151 | -- ["" | ||
| 152 | -- ,"a" ,"b" ,"c" ,"d" | ||
| 153 | -- ,"aa" ,"ab" ,"ac" ,"ad" ,"ba" ,"bb" ,"bc" ,"bd" ,"ca" ,"cb","cc","cd","da","db","dc","dd" | ||
| 154 | -- ,"aaa","aab","aac","aad","aba","abb","abc","abd","aca"] | ||
| 155 | -- | ||
| 156 | -- Prüfe Längen: | ||
| 157 | -- > check alleVariablen 30 | ||
| 158 | -- [1,4,16,9] | ||
| 159 | |||
| 160 | |||
| 161 | |||
| 162 | |||
| 163 | -- A3-4 Instanzen | ||
| 164 | -- Wer sich mit Klassen und Instanzen noch nicht so sicher fühlt, | ||
| 165 | -- sollte zur Übung die automatisch abgeleiteten Instanzdeklaration | ||
| 166 | -- für die Datentypdeklarationen in A3-1 von Hand deklarieren; | ||
| 167 | -- also z.B. | ||
| 168 | -- von "Options" zur Typklassen "Eq" | ||
| 169 | -- von "Tree a" zur Typklasse "Ord" | ||
| 170 | -- | ||
| 171 | -- sie müssen oben in den Datentypdeklarationen dann natürlich | ||
| 172 | -- die entsprechenden Klassen aus Zeile mit "deriving" herauslöschen | ||
| 173 | -- da es ja immer nur _eine_ Instanzdeklaration pro Typ/Klassen-Paar geben darf | ||
| 174 | |||
| 175 | instance Eq a => Eq (Options a) where | ||
| 176 | None == None = True | ||
| 177 | None == _ = False | ||
| 178 | One a == One a' = a == a' | ||
| 179 | One _ == _ = False | ||
| 180 | Two a b == Two a' b' = a == a' && b == b' | ||
| 181 | Two _ _ == _ = False | ||
| 182 | Three a b c == Three a' b' c' = a == a' && b == b' && c == c' | ||
| 183 | Three _ _ _ == _ = False | ||
| 184 | |||
| 185 | instance Ord a => Ord (Tree a) where | ||
| 186 | compare (Node x xs) (Node x' xs') = compare x x' `mappend` compare xs xs' | ||
