154 lines
5.1 KiB
Plaintext
154 lines
5.1 KiB
Plaintext
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))
|
||
|
||
|
||
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))]
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|