5.1 KiB
Aufgabe 1
module Aufgabe1 where
import AdressSys
Applicative style – an abstract pattern for everyday use.
Wiederholung:
(<$>) :: Functor f => (a -> b) -> f a -> f b
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
(=<<) :: Monad m => (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))]