uebung2017_3/src/Aufgabe1.lhs

154 lines
5.1 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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))]