Skip to content
Snippets Groups Projects
Aufgabe1.hs 5.22 KiB
Newer Older
Nicole Dresselhaus's avatar
Nicole Dresselhaus committed
-- 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))
Nicole Dresselhaus's avatar
Nicole Dresselhaus committed


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