diff options
author | Gregor Kleen <gkleen@yggdrasil.li> | 2015-11-13 23:45:26 +0000 |
---|---|---|
committer | Gregor Kleen <gkleen@yggdrasil.li> | 2015-11-13 23:45:26 +0000 |
commit | ab9484b343abd995cba915bb0ba4be8907dfa6ec (patch) | |
tree | f441968094bec070499d24e45e8a29f1315da1f4 /ws2015/ffp/blaetter/03 | |
parent | 14dc76bda755c850f859a4b974c793e694f2b0b4 (diff) | |
download | uni-ab9484b343abd995cba915bb0ba4be8907dfa6ec.tar uni-ab9484b343abd995cba915bb0ba4be8907dfa6ec.tar.gz uni-ab9484b343abd995cba915bb0ba4be8907dfa6ec.tar.bz2 uni-ab9484b343abd995cba915bb0ba4be8907dfa6ec.tar.xz uni-ab9484b343abd995cba915bb0ba4be8907dfa6ec.zip |
Shorter lecture names
Diffstat (limited to 'ws2015/ffp/blaetter/03')
-rw-r--r-- | ws2015/ffp/blaetter/03/FFP_U03_Funktoren.hs | 191 |
1 files changed, 191 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..88ee00f --- /dev/null +++ b/ws2015/ffp/blaetter/03/FFP_U03_Funktoren.hs | |||
@@ -0,0 +1,191 @@ | |||
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` (+ 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 | quadrate' :: [Integer] -- More efficient (probably) | ||
124 | quadrate' = 1 : [2 * x | x <- quadrate'] | ||
125 | |||
126 | -- Zum Testen: | ||
127 | q1 = take 5 quadrate | ||
128 | -- > q1 | ||
129 | -- [1,2,4,8,16] | ||
130 | q2 = quadrate !! 10 | ||
131 | -- > q2 | ||
132 | -- 1024 | ||
133 | |||
134 | |||
135 | -- b) Definieren Sie eine unendliche Liste, welche alle | ||
136 | -- erdenklichen Strings aus den Buchstaben ['a','b','c','d']. | ||
137 | -- Die Reihenfolge ist relativ egal, aber kürzere Strings sollen vor längeren Erscheinen; | ||
138 | -- d.h. "dd" kommt nach "b", aber vor "abc" | ||
139 | |||
140 | alleVariablen :: [String] | ||
141 | alleVariablen = seed : alleVariablen' [seed] | ||
142 | where | ||
143 | seed = "" | ||
144 | vars = ['a','b','c','d'] | ||
145 | alleVariablen' prevs = now ++ alleVariablen' now | ||
146 | where | ||
147 | now = [v : p | v <- vars, p <- prevs] | ||
148 | |||
149 | alleVariablen' :: [String] -- Preferred. | ||
150 | alleVariablen' = "" : [v : p | p <- alleVariablen', v <- vars] | ||
151 | where | ||
152 | vars = ['a', 'b', 'c', 'd'] | ||
153 | |||
154 | -- Zum Testen: | ||
155 | check l x = (map length . groupBy ((==) `on` length)) (take x l) | ||
156 | |||
157 | -- Beispielimplementierung (muss nicht identisch sein): | ||
158 | -- > take 30 alleVariablen | ||
159 | -- ["" | ||
160 | -- ,"a" ,"b" ,"c" ,"d" | ||
161 | -- ,"aa" ,"ab" ,"ac" ,"ad" ,"ba" ,"bb" ,"bc" ,"bd" ,"ca" ,"cb","cc","cd","da","db","dc","dd" | ||
162 | -- ,"aaa","aab","aac","aad","aba","abb","abc","abd","aca"] | ||
163 | -- | ||
164 | -- Prüfe Längen: | ||
165 | -- > check alleVariablen 30 | ||
166 | -- [1,4,16,9] | ||
167 | |||
168 | |||
169 | |||
170 | |||
171 | -- A3-4 Instanzen | ||
172 | -- Wer sich mit Klassen und Instanzen noch nicht so sicher fühlt, | ||
173 | -- sollte zur Übung die automatisch abgeleiteten Instanzdeklaration | ||
174 | -- für die Datentypdeklarationen in A3-1 von Hand deklarieren; | ||
175 | -- also z.B. | ||
176 | -- von "Options" zur Typklassen "Eq" | ||
177 | -- von "Tree a" zur Typklasse "Ord" | ||
178 | -- | ||
179 | -- sie müssen oben in den Datentypdeklarationen dann natürlich | ||
180 | -- die entsprechenden Klassen aus Zeile mit "deriving" herauslöschen | ||
181 | -- da es ja immer nur _eine_ Instanzdeklaration pro Typ/Klassen-Paar geben darf | ||
182 | |||
183 | instance Eq a => Eq (Options a) where | ||
184 | None == None = True | ||
185 | One a == One a' = a == a' | ||
186 | Two a b == Two a' b' = a == a' && b == b' | ||
187 | Three a b c == Three a' b' c' = a == a' && b == b' && c == c' | ||
188 | _ == _ = False | ||
189 | |||
190 | instance Ord a => Ord (Tree a) where | ||
191 | compare (Node x xs) (Node x' xs') = compare x x' `mappend` compare xs xs' | ||