Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
-- Aufgabe 1
-- =========
module Aufgabe1 where
import AdressSys
-- Applicative style – an abstract pattern for everyday use.
-- --------------------------
--
-- Wiederholung:
-- -----------------------------------
-- (<$>) :: (a -> b) -> f a -> f b
-- (<*>) :: f (a -> b) -> f a -> f b
-- (=<<) :: (a -> m b) -> m a -> m b -- (=<<) == flip (>>=)
-- -----------------------------------
--
-- Aus der Vorlesung wissen Sie bereits, dass `[]` und `Maybe` `Applicative`s sind und
-- dass `Applicative` ermöglicht, 'Funktionen im Kontext' auf Werte im Kontext anzuwenden.
-- Außerdem haben Sie `Currying` kennen gelernt. Ein praktisches Muster, das sich hieraus
-- ableiten lässt, ist das folgende:
--
-- pure f <*> x1 <*> x2 <*> .. <*> xn
-- wobei f :: t1 -> t2 -> .. -> tn -> t'
-- x1 :: Applicative m => m t1
-- x2 :: Applicative m => m t2
-- .
-- .
-- xn :: Applicative m => m tn
--
--
-- `pure` hebt die Funktion f in den Kontext m und `<*>` wendet f nach und nach auf alle ihre
-- im Kontext liegenden Argumente t1 bis tn an. Vor dem Hintergrund, dass jedes `Applicative`
-- auch ein `Functor` ist, lässt sich das Muster noch etwas verkürzen:
--
-- pure f <*> x1 <*> x2 <*> ... <*> xn
-- f <$> x1 <*> x2 <*> ... <*> xn
--
--
-- Importiert aus dem Modul AdressSys sind die folgenden Datentypen und Funktionen, die ein
-- ein Datenbanksystem zur Verwaltung persönlicher Daten repräsentieren:
--
-- type ID = Integer
-- type DB = [(ID,[Datum])]
--
-- newtype Age = Age Integer
-- newtype Name = Name String
-- newtype City = City String
-- newtype Email = Email String
-- newtype Phone = Phone String
-- newtype Street = Street String
-- newtype Gender = Gender String
-- newtype Postcode = Postcode String
--
-- data Adress = Adress Name Street PostCode City deriving (Show,Eq)
-- data Public = Public Name (Maybe Age) (Maybe Email) deriving (Show,Eq)
--
-- data Datum = DName Name
-- | DStreet Street
-- | DPostcode Postcode
-- | DEmail Email
-- | DPhone Phone
-- | DGender Gender
-- | DCity City
-- | DAge Age
-- deriving (Show,Eq)
--
-- getName :: [Datum] -> Maybe Name
-- getStreet :: [Datum] -> Maybe Street
-- getPostcode :: [Datum] -> Maybe Postcode
-- getEmail :: [Datum] -> Maybe Email
-- getPhone :: [Datum] -> Maybe Phone
-- getGender :: [Datum] -> Maybe Gender
-- getAge :: [Datum] -> Maybe Age
-- getCity :: [Datum] -> Maybe City
-- -- suchen jeweils das erste Vorkommen aus; gehen Sie davon aus, die Datenstruktur erlaube nur einmaliges Vorkommen
--
-- getDataFromID :: ID -> DB -> Maybe [Datum]
-- -- sucht die zu einer ID zugehörigen Daten aus einer Datenbank aus
db1 = [(1,[DAge (Age 99),DCity (City "Portland,Oregano"),DName (Name "Mona D."),DPostcode (Postcode "42317"),DStreet (Street "Intuition 6")]),(2,[DStreet (Street "Jahnplatz 5"),DName (Name "Alfred Plickateff"),DAge (Age 22),DEmail (Email "a.plickateff@hackage.com")]),(3,[DName (Name "Gerhard Zeh")]),(4,[])]
db2 = [(2,[DAge (Age 54),DCity (City "Bielefeld"),DName (Name "Hans Joachim Meyer"),DPostcode (Postcode "33602"),DStreet (Street "Viktoriastraße 22")]),(6,[DStreet (Street "Dönerteller 1a"),DName (Name "Hannelore Hacker"),DAge (Age 76)]),(3,[DName (Name "Lisa Lista"),DEmail (Email "lisa.lista@web.de"),DAge (Age 7)]),(5,[DName (Name "Alonzo Storch"),DStreet (Street "Antenne 2"),DCity (City "Dingenskirchen"),DPostcode (Postcode "12346")])]
-- zwei Beispieldatenbanken
-- Gegeben eine Liste von persönlichen Daten fassen die folgenden Funktionen `getAdressM` und
-- `getPublicDataM` Adress- bzw. öffentliche Daten zu einem entsprechenden Wert `Adress` bzw.
-- `Public` zusammen; falls nicht alle nötigen Informationen gefunden werden, geben sie `Nothing`
-- zurück.
getAdressM :: [Datum] -> Maybe Adress
getAdressM ds = do
name <- getName ds
street <- getStreet ds
pcode <- getPostcode ds
city <- getCity ds
return (Adress name street pcode city)
getPublicM :: [Datum] -> Maybe Public
getPublicM ds = getName ds >>= \name -> return (Public name (getAge ds) (getEmail ds))
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
-- Implementieren Sie nun zwei Funktionen `getAdressA` und `getPublicDataA`, die das gleiche tun,
-- im Applicative style, d.h. indem Sie das oben beschriebene Muster verwenden.
getAdressA :: [Datum] -> Maybe Adress
getAdressA ds = undefined
getPublicA :: [Datum] -> Maybe Public
getPublicA ds = undefined
-- Definieren Sie abschließend eine Funktion `getManyAdresses` im Applicative style, die unter
-- Verwendung von `getAdressFromID :: ID -> DB -> Maybe Adress` Adressen für eine ganze Liste
-- von `ID`s aus einer Liste von Datenbanken `DB`s aussucht und ausgibt.
getAdressFromID :: ID -> DB -> Maybe Adress
getAdressFromID iD db = getDataFromID iD db >>= getAdressM
getManyAdresses :: [ID] -> [DB] -> [Maybe Adress]
getManyAdresses iDs dbs = undefined
result = unlines $
["Adressen für Nutzer 1 bis 5 (ID) aus db1 und db2: ",
(show $ getManyAdresses [1..5] [db1,db2]),
"Öffentliche Daten für ID 1 db1: ",
(show $ (getDataFromID 1 db1 >>= getPublicA))]