summaryrefslogtreecommitdiff
path: root/ws2015
diff options
context:
space:
mode:
authorGregor Kleen <gkleen@yggdrasil.li>2015-10-31 01:06:10 +0100
committerGregor Kleen <gkleen@yggdrasil.li>2015-10-31 01:06:10 +0100
commitb91812f31131580b751f610164f9c3d24b7c5eaa (patch)
tree588d51ad125c11d36cb4945e1ed86135b7f7530c /ws2015
parentb57ef1aed6a07173ede170c66d32a7450a5dd69d (diff)
downloaduni-b91812f31131580b751f610164f9c3d24b7c5eaa.tar
uni-b91812f31131580b751f610164f9c3d24b7c5eaa.tar.gz
uni-b91812f31131580b751f610164f9c3d24b7c5eaa.tar.bz2
uni-b91812f31131580b751f610164f9c3d24b7c5eaa.tar.xz
uni-b91812f31131580b751f610164f9c3d24b7c5eaa.zip
FFP - Blatt 2
Diffstat (limited to 'ws2015')
-rw-r--r--ws2015/fortgeschrittene_funktionale_programmierung/blaetter/02/FFP_U02_Typklassen.hs206
1 files changed, 206 insertions, 0 deletions
diff --git a/ws2015/fortgeschrittene_funktionale_programmierung/blaetter/02/FFP_U02_Typklassen.hs b/ws2015/fortgeschrittene_funktionale_programmierung/blaetter/02/FFP_U02_Typklassen.hs
new file mode 100644
index 0000000..5f2d936
--- /dev/null
+++ b/ws2015/fortgeschrittene_funktionale_programmierung/blaetter/02/FFP_U02_Typklassen.hs
@@ -0,0 +1,206 @@
1-- Fortgeschrittene Funktionale Programmierung,
2-- LMU, TCS, Wintersemester 2015/16
3-- Steffen Jost, Alexander Isenko
4--
5-- Übungsblatt 02. 28.10.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-- | A2-1 Funktionsdefinitionen
16--
17-- Implementieren Sie folgende grundlegenden,
18-- bekannten Funktionen in Haskell.
19-- Selbst wenn Sie die Funktion nicht kennen,
20-- sollte Ihnen der Typ die korrekte Lösung ermöglichen!
21--
22
23import Prelude hiding (uncurry,flip,(.),map,zip,zipWith,zip,foldl)
24
25import qualified Data.Map as P
26
27-- Hinweis: Das import-Statement müssen Sie jetzt noch nicht verstehen,
28-- es ist nur notwendig zur Vermeidung von Namenskonflikten mit der
29-- Standardbibliothek, welche die meisten dieser Funktionen bereits enthält.
30
31-- a) Uncurrying
32-- > uncurry (/) (1,2) == 0.5
33uncurry :: (a -> b -> c) -> ((a,b) -> c)
34uncurry f (a,b) = f a b
35
36-- b) Anwendung einer Funktion mit zwei Argumenten auf ein Paar
37-- > (1,2) ||> (/) == 0.5
38(||>) :: (a,b) -> (a -> b -> c) -> c
39p ||> f = uncurry f p
40
41
42-- c) Vertauschung der Reihenfolge der Funktionsargumente
43-- > flip (/) 2 1 == 0.5
44flip :: (a -> b -> c) -> (b -> a -> c)
45flip f b a = f a b
46
47
48-- d) Funktionskomposition
49-- > ((\x->x+3) . (\y->y*2)) 1 == 5
50(.) :: (b -> c) -> (a -> b) -> a -> c
51(.) f g x = f $ g x
52
53
54-- e) Map (im Gegensatz zu A1-3 dieses Mal ohne List-Comprehension)
55-- > map (+10) [1,2,3,4] == [11,12,13,14]
56map :: (a -> b) -> [a] -> [b]
57map _ [] = []
58map f (x:xs) = f x : map f xs
59
60
61-- f) zip:
62-- > zip ['a','b','c'] [1,2,3,4,5] = [('a',1),('b',2),('c',3)]
63zip :: [a] -> [b] -> [(a,b)]
64zip [] _ = []
65zip _ [] = []
66zip (x:xs) (y:ys) = (x, y) : zip xs ys
67
68
69-- g) Zippen mit Funktionsanwendung:
70-- > zipWith (+) [1..] [1..3] == [2,4,6]
71zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
72zipWith f xs ys = map (uncurry f) $ zip xs ys
73
74
75-- h) Falten nach links:
76-- > foldl (flip (:) ) [] [1..3] == [3,2,1]
77-- > foldl (\acc x -> x : acc)) [] [1..3] == [3,2,1]
78foldl :: (b -> a -> b) -> b -> [a] -> b
79foldl _ x [] = x
80foldl f x (y:ys) = foldl f (f x y) ys
81
82
83
84-- | A2-2 LambdaTerme
85--
86-- Betrachten Sie die Lösung zur A1-1 g):
87
88data LambdaTerm = LVar Char
89 | LAbs Char LambdaTerm
90 | LApp LambdaTerm LambdaTerm
91
92-- Ein paar Lambda Terme zum Testen:
93lTerm_x = LVar 'x'
94lTerm_y = LVar 'y'
95lTerm_id = LAbs 'x' lTerm_x
96lTerm_xx = LApp lTerm_x lTerm_x
97lTerm_t = LAbs 'x' $ LApp lTerm_y lTerm_xx
98lTerm_yk = LAbs 'y' $ LApp lTerm_t lTerm_t
99
100-- a) Implementieren Sie eine Eq-Instanz für den Datentyp LambdaTerm!
101--
102-- (Wer Lambda-Kalkül kennt: Zur Vereinfachung der Aufgabe
103-- ignorieren wir die übliche alpha-Äquivalenz, d.h.
104-- (LAbs 'x' $ LVar 'x') und (LAbs 'y' $ LVar 'y')
105-- dürfen als verschieden betrachtet werden)
106
107instance Eq LambdaTerm where
108 (LVar a) == (LVar b) = a == b
109 (LVar _) == _ = False
110 (LAbs a t_a) == (LAbs b t_b) = a == b && t_a == t_b
111 (LAbs _ _) == _ = False
112 (LApp t_a t'_a) == (LApp t_b t'_b) = t_a == t_b && t'_a == t'_b
113 (LApp _ _) == _ = False
114
115-- b) Implementieren Sie die eine Show-Instanz für LambdaTerm.
116-- Achten Sie dabei auf eine korrekte Klammerung, aber
117-- verschwenden Sie erst einmal keine Zeit darauf,
118-- überflüssige Klammern zu vermeiden.
119
120instance Show LambdaTerm where
121 show (LVar a) = "LVar '" ++ pure a ++ "'"
122 show (LAbs a t) = "LAbs '" ++ pure a ++ "' (" ++ show t ++ ")"
123 show (LApp t t') = "LApp (" ++ show t ++ ") (" ++ show t' ++ ")"
124
125
126-- | A2-3 Klassendeklaration
127--
128-- a) Deklarieren Sie eine Klasse "FinMap" für endliche partielle Abbildungen, welche folgende Operationen bereitsstellt:
129-- 1) "emptyM" liefert eine leere Abbildung
130-- 2) "insertM x a m" fügt die Abbildung [x->a] in die Abbildung m ein.
131-- Falls x schon enthalten war, dann wird es überschrieben.
132-- 3) "lookupM x m" liefert Nothing zurück, falls x nicht in m enthalten ist;
133-- ansonsten wird der für x gespeicherte Wert z zurückgeliefert (in Just verpackt)
134-- Die Funktion "lookupM" darf dabei annehmen, dass für x eine Vergleichsoperation vorliegt!?!
135
136class FinMap m where
137 emptyM :: m k v
138 insertM :: Ord k => k -> v -> m k v -> m k v
139 lookupM :: Ord k => k -> m k v -> Maybe v
140 -- Can we get around using constraints here without using the MultiParamTypeClasses language extension?
141
142-- b) Machen Sie folgenden Datentyp zu einer Instanz der Typklasse Map:
143
144-- data AL a b = AL [(a,b)]
145newtype AL a b = AL [(a,b)] -- Äquivalent zur vorherigen Zeile.
146 -- newtype kann und darf verwenden werden,
147 -- wenn man nur einen Konstruktor mit nur einem Argument hat.
148 -- Dies erlaubt GHC eine Optimierung durchzuführen.
149 deriving (Show, Read, Eq)
150
151instance FinMap AL where
152 emptyM = AL $ []
153 insertM x a (AL m) = AL $ (x, a) : [p | p@(x', _) <- m, x' /= x]
154 lookupM x (AL m) = listToMaybe [y | (x', y) <- m, x' == x] -- Due to lazyness this is no slower than explicitly short-circuiting the search
155 where
156 -- This is part of Data.Maybe
157 listToMaybe [] = Nothing
158 listToMaybe (x:_) = Just x
159
160
161---- Werte zum anschließendem Testen, auskommentieren,
162---- sobald Klasse und Instanz definiert wurden:
163testMap0 :: AL Int Bool
164testMap0 = emptyM
165testMap1 = insertM 1 False testMap0
166testMap2 = insertM 3 False testMap1
167testMap3 = insertM 4 True testMap2
168testMap4 = insertM 2 True testMap3
169
170
171-- Hinweis:
172-- Partielle Abbildungen wie hier durch Assoziationslisten zu implementieren,
173-- ist nicht bensonders effizient, da der Zugriff auf ein Element im Allgemeinen
174-- den Aufwand O(n) hat (man muss die ganze Liste abklappern - es könnte sich ja
175-- um das letzte Element der Liste handeln).
176-- Mit Suchbäumen läßt sich der Aufwand bekanntermaßen auf O(log n) reduzieren.
177-- Wer noch Lust & Zeit hat, kann versuchen, dies selbst zu implementieren
178-- und zur einer weiteren Instanz von FinMap machen.
179--
180-- Die Standardbibliothek sieht zur Abstraktion hier keine solche Klasse vor,
181-- sondern bietet lediglich eine konkrete, effiziente Implementierung von
182-- endlichen Abbildungen an: Data.Map, welche wir in der kommenden Vorlesung
183-- betrachten werden.
184--
185-- Dies kann man natürlich ganz schnell zu einer Instanz von FinMap machen. Wie?
186
187data Map k v = Tip
188 | Branch k v (Map k v) (Map k v)
189
190instance FinMap Map where
191 emptyM = Tip
192 insertM k v Tip = Branch k v Tip Tip
193 insertM k v (Branch k' v' lt gt)
194 | k == k' = Branch k v lt gt
195 | k < k' = Branch k' v' (insertM k v lt) gt
196 | otherwise = Branch k' v' lt (insertM k v gt)
197 lookupM _ Tip = Nothing
198 lookupM k (Branch k' v' lt gt)
199 | k == k' = Just v'
200 | k < k' = lookupM k lt
201 | otherwise = lookupM k gt
202
203instance FinMap P.Map where
204 emptyM = P.empty
205 insertM = P.insert
206 lookupM = P.lookup