summaryrefslogtreecommitdiff
path: root/ws2015
diff options
context:
space:
mode:
authorGregor Kleen <gkleen@yggdrasil.li>2015-11-18 16:50:48 +0100
committerGregor Kleen <gkleen@yggdrasil.li>2015-11-18 16:50:48 +0100
commit17af38d7b43fbb8d2105de5e01fe27795a724119 (patch)
tree64bd7e24996d5f7e2eabdfc82df285926a9cf866 /ws2015
parentdc30f414e08e3df442824b4e4fb57b8ae4f14b18 (diff)
downloaduni-17af38d7b43fbb8d2105de5e01fe27795a724119.tar
uni-17af38d7b43fbb8d2105de5e01fe27795a724119.tar.gz
uni-17af38d7b43fbb8d2105de5e01fe27795a724119.tar.bz2
uni-17af38d7b43fbb8d2105de5e01fe27795a724119.tar.xz
uni-17af38d7b43fbb8d2105de5e01fe27795a724119.zip
FFP - 05
Diffstat (limited to 'ws2015')
-rw-r--r--ws2015/ffp/blaetter/05/FFP_U05_ApplikativeF.hs219
1 files changed, 219 insertions, 0 deletions
diff --git a/ws2015/ffp/blaetter/05/FFP_U05_ApplikativeF.hs b/ws2015/ffp/blaetter/05/FFP_U05_ApplikativeF.hs
new file mode 100644
index 0000000..4f68f18
--- /dev/null
+++ b/ws2015/ffp/blaetter/05/FFP_U05_ApplikativeF.hs
@@ -0,0 +1,219 @@
1-- Fortgeschrittene Funktionale Programmierung,
2-- LMU, TCS, Wintersemester 2015/16
3-- Steffen Jost, Alexander Isenko
4--
5-- Übungsblatt 05. 18.11.2015
6--
7-- Thema: Applikative Funktoren
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-- | Ziele für dieses Blatt: |
17-- | * Instanzen für eigene Datentypen schreiben können |
18-- | * Applicative Gesetze und Klassenfunktionen kennenlernen |
19-- | * Klasse Traversable kennenlernen |
20-- |_____________________________________________________________________|
21-- |
22-- λ_/
23-- /|
24-- / \
25
26import Prelude hiding (Traversable, traverse)
27import Data.Functor
28import Control.Applicative
29
30---- A5-1 Instanzen von Applikativen Funktoren
31--
32-- Gegeben ist eine alternative Datentypdeklaration
33-- für gewöhnliche Listen:
34
35data List a = Nil | Cons a (List a)
36 deriving (Eq, Show)
37
38{-
39-- Manuell definierte Show-Instanz für gewöhnliche Schreibweise:
40instance Show a => Show (List a) where
41 show Nil = "[]"
42 show (Cons x Nil) = show x ++ " : " ++ "[]"
43 show (Cons x xs) = show x ++ " : " ++ show xs
44--
45-- Für den Ausdruck gilt damit folgende Schreibweise:
46-- [] entspricht Nil
47-- (h:t) entspricht (Cons h t)
48-}
49
50
51-- In der Vorlesung wurden zwei Möglichkeiten vorgestellt,
52-- Listen zu Applikativen Funktoren zu machen.
53-- In dieser Aufgabe sollen Sie dies nachvollziehen,
54-- d.h. schauen Sie dabei also möglichst _NICHT_ in Folien 4-19 ff.
55-- sondern nur die davor!
56
57
58-- a) Betrachten Sie folgenden fehlerhaften Lösungsversuch.
59-- Der Lösungsversuch kompiliert und lässt sich ausführen,
60-- aber die Gesetze eines Applikativen Funktors werden
61-- missachtet.
62-- Finden Sie durch ausprobieren mindestens ein Gesetz,
63-- welches missachtet wird!
64--
65-- Beispiel:
66-- > pure id <*> Nil2 :: List2 Int -- explizite Typangabe
67-- Nil2
68-- liefert noch keinen Hinweis daruf, dass z.B. das Gesetz "Identität"
69-- verletzt wird -- aber vielleicht wird es für andere Werte als Nil2 verletzt,
70-- oder vielleicht wird ein anderes Gesetz verletzt?! Finden Sie es heraus!
71--
72-- Hinweis: Achten Sie bei Ihren Tests in GHCI darauf,
73-- dass auch die richtige Instanz verwendet wird,
74-- z.B. durch explizite Angabe des Typs!
75
76data List2 a = Nil2 | Cons2 a (List2 a) deriving (Show, Eq)
77
78instance Functor List2 where
79 fmap _ Nil2 = Nil2
80 fmap f (Cons2 x xs) = Cons2 (f x) (fmap f xs)
81
82instance Applicative List2 where
83 -- pure :: a -> List2 a -- Typsignaturen sind in Instanzdeklarationen unzulässig
84 pure x = Nil2
85 -- <*> :: List2 (a -> b) -> List2 a -> List2 b
86 Nil2 <*> _ = Nil2
87 (Cons2 x xs) <*> Nil2 = Nil2
88 (Cons2 x xs) <*> Cons2 y ys = Cons2 (x y) (xs <*> ys)
89
90{-
91 - Nimm:
92 - ghci> pure id <*> (Cons2 () Nil2)
93 - Nil2
94 - Dies verletzt Identität.
95 -}
96
97-- b) Ist folgende Nachbesserung zur a) wirklich besser?
98-- Werden nun alle Gesetze respektiert?
99
100data List3 a = Nil3 | Cons3 a (List3 a) deriving (Show, Eq)
101
102instance Functor List3 where
103 fmap f xs = pure f <*> xs
104
105instance Applicative List3 where
106 -- pure :: a -> List3 a
107 pure x = Cons3 x Nil3
108 -- <*> :: List3 (a -> b) -> List3 a -> List3 b
109 Nil3 <*> _ = Nil3
110 (Cons3 x xs) <*> Nil3 = Nil3
111 (Cons3 x xs) <*> Cons3 y ys =
112 Cons3 (x y) (xs <*> ys)
113
114{-
115 - Nimm:
116 - ghci> pure id <*> (Cons3 () (Cons3 () Nil3))
117 - Cons3 () Nil3
118 - Auch dies verletzt Identität.
119 -}
120
121-- c) Machen Sie es nun selbst richtig!
122-- Machen Sie den Typ List zu einer korrekten Instanz von Applicative!
123-- Experimentieren Sie anschliessend mit ein paar Beispielen.
124
125instance Functor List where
126 fmap f xs = pure f <*> xs
127
128-- Analog zu ZipList
129instance Applicative List where
130 pure x = Cons x (pure x)
131 (Cons x xs) <*> (Cons y ys) = Cons (x y) (xs <*> ys)
132 _ <*> _ = Nil
133
134
135---- A5-2 Kontextfolge
136--
137-- Gegeben ist folgende Funktionsdefinition,
138-- bei der leider die Typsignatur fehlt.
139
140-- a)
141-- Berechnen Sie die Typsignatur selbst manuell, also ohne einfach GHCI zu fragen!
142-- Schlagen Sie ggf. die Typen von pure, (:), (<$>) und (<*>) nach!
143
144folgeA :: Applicative f => [f a] -> f [a]
145folgeA [] = pure []
146folgeA (h:t) = (:) <$> h <*> folgeA t
147
148
149-- b)
150-- Wieder eine Denksportaufgabe:
151-- zu welchem Ergebnis wertet folgende Ausdrücke aus:
152
153a5_2b1 = folgeA [Just 1, Just 27, Just 2]
154-- Just [1, 27, 2]
155a5_2b2 = folgeA [Just 4, Just (sqrt 27), Just (sum [1..100]), Nothing, Just 0]
156-- Nothing
157a5_2b3 = folgeA [[1,2],[3],[4,5]]
158-- [[1,3,4],[1,3,5],[2,3,4],[2,3,5]]
159a5_2b4 = folgeA [ZipList [1,2], ZipList [3], ZipList [4,5]]
160-- ZipList [1, 3, 4]
161a5_2b5 = folgeA [(*2),(+1), negate] $ 3
162-- [6, 4, -3]
163
164
165
166
167---- A5-3 Anwendung von Applikativen Funktoren mit der Typklasse Traversable
168--
169--
170-- Gegeben ist folgende vereinfachte Version
171-- der Typklasse Traversable (im Original siehe Modul Data.Traversable:
172--
173
174class Traversable t where
175 traverse :: Applicative f => (a -> f b) -> t a -> f (t b)
176
177 sequenceA :: Applicative f => t (f a) -> f (t a)
178 sequenceA = traverse id
179
180
181-- Weiterhin ist folgender Datentyp für Binäre Bäume gegeben:
182
183data Baum a = Blatt a | Gabel (Baum a) a (Baum a) | Astloch
184 deriving (Show, Eq)
185
186test1 = Gabel (Blatt 42) 1 (Gabel (Gabel Astloch 69 $ Blatt 7) 44 Astloch)
187test2 = Gabel (Blatt [42]) [1,2,3] (Gabel (Gabel Astloch [69,96] $ Blatt [7]) [44,101,0] Astloch)
188
189
190-- a) Machen Sie den Typ "Baum" zu einer Instanz
191-- der Tyklasse Traversable!
192--
193-- Hinweis:
194-- Schauen Sie sich _NICHT_ das Modul Data.Traversable
195-- aus der Standardbibliothek an, da dessen Dokumentation
196-- bereits die Lösung zu dieser Aufgabe als Beispiel behandelt.
197
198instance Traversable Baum where
199 traverse _ Astloch = pure Astloch
200 traverse f (Blatt x) = Blatt <$> f x
201 traverse f (Gabel c1 x c2) = Gabel <$> traverse f c1 <*> f x <*> traverse f c2
202
203-- Beispiele:
204-- > take 1 $ drop 4 $ traverse (\x->[x,-x]) test1
205-- [Gabel (Blatt 42) 1 (Gabel (Gabel Astloch (-69) (Blatt 7)) 44 Astloch)]
206--
207-- > traverse (\x->if x>0 then Just x else Nothing) test1
208-- Just (Gabel (Blatt 42) 1 (Gabel (Gabel Astloch 69 (Blatt 7)) 44 Astloch))
209--
210-- > traverse (\x->if even x then Just x else Nothing) test1
211-- Nothing
212--
213-- > take 2 $ drop 5 $ sequenceA test2
214-- [Gabel (Blatt 42) 1 (Gabel (Gabel Astloch 96 (Blatt 7)) 0 Astloch),Gabel (Blatt 42) 2 (Gabel (Gabel Astloch 69 (Blatt 7)) 44 Astloch)]
215
216
217-- b) Gibt es einen Zusammenhang zwischen folgeA und sequenceA?
218
219-- folgeA ist sequenceA spezialisiert auf []