summaryrefslogtreecommitdiff
path: root/ws2015/ffp/blaetter/03/FFP_U03_Funktoren.hs
diff options
context:
space:
mode:
Diffstat (limited to 'ws2015/ffp/blaetter/03/FFP_U03_Funktoren.hs')
-rw-r--r--ws2015/ffp/blaetter/03/FFP_U03_Funktoren.hs191
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
16import Data.List (groupBy)
17import 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)
31data 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
37instance 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:
44testO0 = None
45testO1 = One 4.2
46testO2 = Two 4.2 6.9
47-- Tests auskommentierbar, sobald Functor Instanz definiert:
48testa1 = None == fmap (+2) testO0
49testa2 = Two 8.4 13.8 == fmap (*2) testO2
50
51
52-- b)
53data Tree a = Node a [Tree a]
54 deriving (Eq, Show)
55
56--Hilfsfunktion
57leaf :: a -> Tree a
58leaf x = Node x []
59
60instance Functor Tree where
61 fmap f (Node a xs) = Node (f a) $ map (fmap f) xs
62
63-- Zum Testen:
64testT1 = Node 1 [Node 2 [Node 3 [], leaf 4, Node 5 [leaf 6, leaf 7, leaf 8]], leaf 9, Node 10 [leaf 11]]
65testT2 = 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:
67testb1 = 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
120quadrate :: [Integer]
121quadrate = map (2^) [0..]
122
123quadrate' :: [Integer] -- More efficient (probably)
124quadrate' = 1 : [2 * x | x <- quadrate']
125
126-- Zum Testen:
127q1 = take 5 quadrate
128-- > q1
129-- [1,2,4,8,16]
130q2 = 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
140alleVariablen :: [String]
141alleVariablen = 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
149alleVariablen' :: [String] -- Preferred.
150alleVariablen' = "" : [v : p | p <- alleVariablen', v <- vars]
151 where
152 vars = ['a', 'b', 'c', 'd']
153
154-- Zum Testen:
155check 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
183instance 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
190instance Ord a => Ord (Tree a) where
191 compare (Node x xs) (Node x' xs') = compare x x' `mappend` compare xs xs'