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 /ws2015/FFP/blaetter | |
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
Diffstat (limited to 'ws2015/FFP/blaetter')
-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' | ||