• Keine Ergebnisse gefunden

Abstrakte Datentypen

N/A
N/A
Protected

Academic year: 2022

Aktie "Abstrakte Datentypen"

Copied!
6
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Praktische Informatik 3: Funktionale Programmierung Vorlesung 8 vom 04.12.2018: Abstrakte Datentypen

Christoph Lüth Universität Bremen Wintersemester 2018/19

16:03:11 2018-12-18 1 [42]

Organisatorisches

I Morgen istTag der Lehre

IMittwochs-Tutorienfallen aus

IDonnerstags-Tutorien finden statt.

I Abgabe des 8. Übungsblattes in Gruppen zudreiStudenten.

IBittejetzteine Gruppe suchen!

I Klausurtermine:

IÜbungsklausur: 17.12.2018 10– 12

IHauptklausur: 08.03.2019 10– 14

PI3 WS 18/19 2 [42]

Fahrplan

I Teil I: Funktionale Programmierung im Kleinen

I Teil II: Funktionale Programmierung im Großen

I Abstrakte Datentypen

I Signaturen und Eigenschaften

I Teil III: Funktionale Programmierung im richtigen Leben

PI3 WS 18/19 3 [42]

Inhalt

I Abstrakte Datentypen

IAllgemeine Einführung

IRealisierung in Haskell

IBeispiele

PI3 WS 18/19 4 [42]

Warum Modularisierung?

I Übersichtlichkeit der Module

Lesbarkeit

I Getrennte Übersetzung

technischeHandhabbarkeit

I Verkapselung

konzeptionelleHandhabbarkeit

PI3 WS 18/19 5 [42]

Abstrakte Datentypen

Definition (Abstrakter Datentyp)

Einabstrakter Datentyp(ADT) besteht aus einem (oder mehreren) TypenundOperationendarauf, mit folgenden Eigenschaften:

I Werte des Typen können nur über die bereitgestellten Operationen erzeugt werden

I Eigenschaften von Werten des Typen werden nur über die bereitgestellten Operationen beobachtet

I Einhaltung vonInvariantenüber dem Typ kann garantiert werden

Implementationvon ADTs in einer Programmiersprache:

I benötigt Möglichkeit derKapselung(Einschränkung der Sichtbarkeit) I bspw. durchModuleoderObjekte

PI3 WS 18/19 6 [42]

ADTs vs. algebraische Datentypen

I Algebraische Datentypen

I Frei erzeugt

I Keine Einschränkungen

I Insbesondere keine Gleichheiten ([ ]6= x : xs,x : l s6= y : l setc.) I ADTs:

I Einschränkungen und Invarianten möglich

I Gleichheiten möglich

ADTs in Haskell: Module

I Einschränkung der Sichtbarkeit durchVerkapselung

I Modul: Kleinste verkapselbareEinheit

I EinModulumfaßt:

IDefinitionenvon Typen, Funktionen, Klassen

IDeklarationder nach außensichtbarenDefinitionen

I Gleichzeitig: Modul ˆ= Übersetzungseinheit (getrennte Übersetzung)

(2)

Module: Syntax

I Syntax:

moduleName( Bezeichner )whereRumpf

I Bezeichner können leer sein (dann wird alles exportiert) I Bezeichner sind:

I Typen:T,T(c1 , . . . , cn),T( . . )

I Klassen:C,C( f1 , . . . , fn ),C( . . )

I Andere Bezeichner:Werte,Felder,Klassenmethoden

I ImportierteModule:moduleM

I Typsynonyme und Klasseninstanzen bleiben sichtbar I Module könnenrekursivsein(don’t try at home)

PI3 WS 18/19 9 [42]

Refakturierung im Einkaufsparadies

module Shoppe4 where import Data.Maybe

−−Modellierung der Artikel.

data Apfelsorte = Boskoop | CoxOrange | GrannySmith deriving (Eq, Show) apreis :: Apfelsorte→Int apreis Boskoop = 55 apreis CoxOrange = 60 apreis GrannySmith = 50 data Kaesesorte = Gouda | Appenzeller

deriving (Eq, Show) kpreis :: Kaesesorte→Double kpreis Gouda = 1450 kpreis Appenzeller = 2270 data Bio = Bio | Konv

deriving (Eq, Show) data Art ikel =

Apfel Apfelsorte | Eier

| Kaese Kaesesorte | Schinken

| Salami | Milch Bio deriving (Eq, Show) data Menge = Stueck Int | Gramm Int | Lit er Double

deriving (Eq, Show) type Preis = Maybe Int preis :: Art ikel→Menge→Preis preis ( Apfel a) ( Stueck n) = Just (n∗apreis a) preis Eier ( Stueck n)= Just (n∗20) preis (Kaese k)(Gramm g) = Just ( round( fromIntegral g∗1000∗kpreis k)) preis Schinken (Gramm g) = Just ( div (g∗199) 100) preis Salami (Gramm g)= Just ( div (g∗159) 100) preis ( Milch bio) ( Lit er l ) =

Just ( round ( l∗case bio of Bio→119; Konv→69)) preis = Nothing

−−Addition von Mengen addiere :: Menge→Menge→Menge addiere ( Stueck i ) ( Stueck j )= Stueck ( i + j ) addiere (Gramm g) (Gramm h) = Gramm (g+ h) addiere ( Lit er l ) ( Lit er m) = Lit er ( l + m) addiere m n = error (” addiere: ” ++ show m++ ” und ” ++ show n)

−−Posten:

data Posten = Posten Art ikel Menge deriving (Eq, Show) cent :: Posten→Int

cent ( Posten a m) = fromMaybe 0 ( preis a m)−−gibt keinen Laufzeitfehler!

−−Lagerhaltung:

data Lager = Lager [ Posten]

deriving (Eq, Show) leeresLager :: Lager leeresLager = Lager [ ]

suche :: Art ikel→Lager→Maybe Menge suche a ( Lager ps) =

listToMaybe [ m | Posten la m←ps,la == a ] einlagern :: Art ikel→Menge→Lager→Lager einlagern a m ( Lager ps) =

let hinein a m [ ] = [ Posten a m]

hinein a m ( Posten al ml: l )

| a == al= ( Posten a ( addiere m ml) : l )

| otherwise = ( Posten al ml: hinein a m l ) in case preis a m of

Nothing→Lager ps

→Lager ( hinein a m ps) data Einkaufswagen = Ekwg [ Posten]

deriving (Eq, Show) leererWagen :: Einkaufswagen leererWagen = Ekwg [ ]

einkauf :: Art ikel→Menge→Einkaufswagen→Einkaufswagen einkauf a m (Ekwg ps)

| isJust ( preis a m) = Ekwg ( Posten a m: ps)

| otherwise = Ekwg ps kasse :: Einkaufswagen→Int kasse (Ekwg ps) = sum (map cent ps) kassenbon :: Einkaufswagen→String kassenbon ew@(Ekwg ps) =

”Bob’ s Aulde Grocery Shoppe\n\n” ++

” Art ikel Menge Preis\n” ++

”−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−\n” ++

concatMap art ikel ps ++

”=====================================\n” ++

”Summe: ” ++ formatR 31 (showEuro ( kasse ew)) art ikel :: Posten→String art ikel p@( Posten a m) =

formatL 20 (show a) ++

formatR 7 (menge m) ++

formatR 10 (showEuro ( cent p)) ++ ” \n”

menge :: Menge→String menge ( Stueck n) = show n++ ” St”

menge (Gramm g) = show g++ ” g. ” menge ( Lit er l ) = show l++ ” l . ” formatL :: Int→String→String formatL n st r = take n ( st r++ replicat e n ’ ’ ) formatR :: Int→String→String formatR n st r =

take n ( replicat e (n−length st r ) ’ ’ ++ st r ) showEuro :: Int→String showEuro i =

show ( div i 100) ++ ” . ” ++

show (mod ( div i 10) 10) ++

show (mod i 10)++ ” EU”

inventur :: Lager→Int inventur ( Lager l ) = sum (map cent l )

Artikel

module Shoppe4 where import Data.Maybe

−−Modellierung der Artikel.

data Apfelsorte = Boskoop | CoxOrange | GrannySmith deriving (Eq, Show) apreis :: Apfelsorte→Int apreis Boskoop = 55 apreis CoxOrange = 60 apreis GrannySmith = 50 data Kaesesorte = Gouda | Appenzeller

deriving (Eq, Show) kpreis :: Kaesesorte→Double kpreis Gouda = 1450 kpreis Appenzeller = 2270 data Bio = Bio | Konv

deriving (Eq, Show) data Art ikel =

Apfel Apfelsorte | Eier

| Kaese Kaesesorte | Schinken

| Salami | Milch Bio deriving (Eq, Show) data Menge = Stueck Int | Gramm Int | Lit er Double

deriving (Eq, Show) type Preis = Maybe Int preis :: Art ikel→Menge→Preis preis ( Apfel a) ( Stueck n) = Just (n∗apreis a) preis Eier ( Stueck n)= Just (n∗20) preis (Kaese k)(Gramm g) = Just ( round( fromIntegral g∗1000∗kpreis k)) preis Schinken (Gramm g) = Just ( div (g∗199) 100) preis Salami (Gramm g)= Just ( div (g∗159) 100) preis ( Milch bio) ( Lit er l ) =

Just ( round ( l∗case bio of Bio→119; Konv→69)) preis = Nothing

−−Addition von Mengen addiere :: Menge→Menge→Menge addiere ( Stueck i ) ( Stueck j )= Stueck ( i + j ) addiere (Gramm g) (Gramm h) = Gramm (g+ h) addiere ( Lit er l ) ( Lit er m) = Lit er ( l + m) addiere m n = error (” addiere: ” ++ show m++ ” und ” ++ show n)

−−Posten:

data Posten = Posten Art ikel Menge deriving (Eq, Show) cent :: Posten→Int

cent ( Posten a m) = fromMaybe 0 ( preis a m)−−gibt keinen Laufzeitfehler!

−−Lagerhaltung:

data Lager = Lager [ Posten]

deriving (Eq, Show) leeresLager :: Lager leeresLager = Lager [ ]

suche :: Art ikel→Lager→Maybe Menge suche a ( Lager ps) =

listToMaybe [ m | Posten la m←ps,la == a ] einlagern :: Art ikel→Menge→Lager→Lager einlagern a m ( Lager ps) =

let hinein a m [ ] = [ Posten a m]

hinein a m ( Posten al ml: l )

| a == al= ( Posten a ( addiere m ml) : l )

| otherwise = ( Posten al ml: hinein a m l ) in case preis a m of

Nothing→Lager ps

→Lager ( hinein a m ps) data Einkaufswagen = Ekwg [ Posten]

deriving (Eq, Show) leererWagen :: Einkaufswagen leererWagen = Ekwg [ ]

einkauf :: Art ikel→Menge→Einkaufswagen→Einkaufswagen einkauf a m (Ekwg ps)

| isJust ( preis a m) = Ekwg ( Posten a m: ps)

| otherwise = Ekwg ps kasse :: Einkaufswagen→Int kasse (Ekwg ps) = sum (map cent ps) kassenbon :: Einkaufswagen→String kassenbon ew@(Ekwg ps) =

”Bob’ s Aulde Grocery Shoppe\n\n” ++

” Art ikel Menge Preis\n” ++

”−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−\n” ++

concatMap art ikel ps ++

”=====================================\n” ++

”Summe: ” ++ formatR 31 (showEuro ( kasse ew)) art ikel :: Posten→String art ikel p@( Posten a m) =

formatL 20 (show a) ++

formatR 7 (menge m) ++

formatR 10 (showEuro ( cent p)) ++ ” \n”

menge :: Menge→String menge ( Stueck n) = show n++ ” St”

menge (Gramm g) = show g++ ” g. ” menge ( Lit er l ) = show l++ ” l . ” formatL :: Int→String→String formatL n st r = take n ( st r++ replicat e n ’ ’ ) formatR :: Int→String→String formatR n st r =

take n ( replicat e (n−length st r ) ’ ’ ++ st r ) showEuro :: Int→String showEuro i =

show ( div i 100) ++ ” . ” ++

show (mod ( div i 10) 10) ++

show (mod i 10)++ ” EU”

inventur :: Lager→Int inventur ( Lager l ) = sum (map cent l )

Posten Artikel

module Shoppe4 where import Data.Maybe

−−Modellierung der Artikel.

data Apfelsorte = Boskoop | CoxOrange | GrannySmith deriving (Eq, Show) apreis :: Apfelsorte→Int apreis Boskoop = 55 apreis CoxOrange = 60 apreis GrannySmith = 50 data Kaesesorte = Gouda | Appenzeller

deriving (Eq, Show) kpreis :: Kaesesorte→Double kpreis Gouda = 1450 kpreis Appenzeller = 2270 data Bio = Bio | Konv

deriving (Eq, Show) data Art ikel =

Apfel Apfelsorte | Eier

| Kaese Kaesesorte | Schinken

| Salami | Milch Bio deriving (Eq, Show) data Menge = Stueck Int | Gramm Int | Lit er Double

deriving (Eq, Show) type Preis = Maybe Int preis :: Art ikel→Menge→Preis preis ( Apfel a) ( Stueck n) = Just (n∗apreis a) preis Eier ( Stueck n)= Just (n∗20) preis (Kaese k)(Gramm g) = Just ( round( fromIntegral g∗1000∗kpreis k)) preis Schinken (Gramm g) = Just ( div (g∗199) 100) preis Salami (Gramm g)= Just ( div (g∗159) 100) preis ( Milch bio) ( Lit er l ) =

Just ( round ( l∗case bio of Bio→119; Konv→69)) preis = Nothing

−−Addition von Mengen addiere :: Menge→Menge→Menge addiere ( Stueck i ) ( Stueck j )= Stueck ( i + j ) addiere (Gramm g) (Gramm h) = Gramm (g+ h) addiere ( Lit er l ) ( Lit er m) = Lit er ( l + m) addiere m n = error (” addiere: ” ++ show m++ ” und ” ++ show n)

−−Posten:

data Posten = Posten Art ikel Menge deriving (Eq, Show) cent :: Posten→Int

cent ( Posten a m) = fromMaybe 0 ( preis a m)−−gibt keinen Laufzeitfehler!

−−Lagerhaltung:

data Lager = Lager [ Posten]

deriving (Eq, Show) leeresLager :: Lager leeresLager = Lager [ ]

suche :: Art ikel→Lager→Maybe Menge suche a ( Lager ps) =

listToMaybe [ m | Posten la m←ps,la == a ] einlagern :: Art ikel→Menge→Lager→Lager einlagern a m ( Lager ps) =

let hinein a m [ ] = [ Posten a m]

hinein a m ( Posten al ml: l )

| a == al= ( Posten a ( addiere m ml) : l )

| otherwise = ( Posten al ml: hinein a m l ) in case preis a m of

Nothing→Lager ps

→Lager ( hinein a m ps) data Einkaufswagen = Ekwg [ Posten]

deriving (Eq, Show) leererWagen :: Einkaufswagen leererWagen = Ekwg [ ]

einkauf :: Art ikel→Menge→Einkaufswagen→Einkaufswagen einkauf a m (Ekwg ps)

| isJust ( preis a m) = Ekwg ( Posten a m: ps)

| otherwise = Ekwg ps kasse :: Einkaufswagen→Int kasse (Ekwg ps) = sum (map cent ps) kassenbon :: Einkaufswagen→String kassenbon ew@(Ekwg ps) =

”Bob’ s Aulde Grocery Shoppe\n\n” ++

” Art ikel Menge Preis\n” ++

”−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−\n” ++

concatMap art ikel ps ++

”=====================================\n” ++

”Summe: ” ++ formatR 31 (showEuro ( kasse ew)) art ikel :: Posten→String art ikel p@( Posten a m) =

formatL 20 (show a) ++

formatR 7 (menge m) ++

formatR 10 (showEuro ( cent p)) ++ ” \n”

menge :: Menge→String menge ( Stueck n) = show n++ ” St”

menge (Gramm g) = show g++ ” g. ” menge ( Lit er l ) = show l++ ” l . ” formatL :: Int→String→String formatL n st r = take n ( st r++ replicat e n ’ ’ ) formatR :: Int→String→String formatR n st r =

take n ( replicat e (n−length st r ) ’ ’ ++ st r ) showEuro :: Int→String showEuro i =

show ( div i 100) ++ ” . ” ++

show (mod ( div i 10) 10) ++

show (mod i 10)++ ” EU”

inventur :: Lager→Int inventur ( Lager l ) = sum (map cent l )

Lager

Lager Posten Artikel

module Shoppe4 where import Data.Maybe

−−Modellierung der Artikel.

data Apfelsorte = Boskoop | CoxOrange | GrannySmith deriving (Eq, Show) apreis :: Apfelsorte→Int apreis Boskoop = 55 apreis CoxOrange = 60 apreis GrannySmith = 50 data Kaesesorte = Gouda | Appenzeller

deriving (Eq, Show) kpreis :: Kaesesorte→Double kpreis Gouda = 1450 kpreis Appenzeller = 2270 data Bio = Bio | Konv

deriving (Eq, Show) data Art ikel =

Apfel Apfelsorte | Eier

| Kaese Kaesesorte | Schinken

| Salami | Milch Bio deriving (Eq, Show) data Menge = Stueck Int | Gramm Int | Lit er Double

deriving (Eq, Show) type Preis = Maybe Int preis :: Art ikel→Menge→Preis preis ( Apfel a) ( Stueck n) = Just (n∗apreis a) preis Eier ( Stueck n)= Just (n∗20) preis (Kaese k)(Gramm g) = Just ( round( fromIntegral g∗1000∗kpreis k)) preis Schinken (Gramm g) = Just ( div (g∗199) 100) preis Salami (Gramm g)= Just ( div (g∗159) 100) preis ( Milch bio) ( Lit er l ) =

Just ( round ( l∗case bio of Bio→119; Konv→69)) preis = Nothing

−−Addition von Mengen addiere :: Menge→Menge→Menge addiere ( Stueck i ) ( Stueck j )= Stueck ( i + j ) addiere (Gramm g) (Gramm h) = Gramm (g+ h) addiere ( Lit er l ) ( Lit er m) = Lit er ( l + m) addiere m n = error (” addiere: ” ++ show m++ ” und ” ++ show n)

−−Posten:

data Posten = Posten Art ikel Menge deriving (Eq, Show) cent :: Posten→Int

cent ( Posten a m) = fromMaybe 0 ( preis a m)−−gibt keinen Laufzeitfehler!

−−Lagerhaltung:

data Lager = Lager [ Posten]

deriving (Eq, Show) leeresLager :: Lager leeresLager = Lager [ ]

suche :: Art ikel→Lager→Maybe Menge suche a ( Lager ps) =

listToMaybe [ m | Posten la m←ps,la == a ] einlagern :: Art ikel→Menge→Lager→Lager einlagern a m ( Lager ps) =

let hinein a m [ ] = [ Posten a m]

hinein a m ( Posten al ml: l )

| a == al= ( Posten a ( addiere m ml) : l )

| otherwise = ( Posten al ml: hinein a m l ) in case preis a m of

Nothing→Lager ps

→Lager ( hinein a m ps) data Einkaufswagen = Ekwg [ Posten]

deriving (Eq, Show) leererWagen :: Einkaufswagen leererWagen = Ekwg [ ]

einkauf :: Art ikel→Menge→Einkaufswagen→Einkaufswagen einkauf a m (Ekwg ps)

| isJust ( preis a m) = Ekwg ( Posten a m: ps)

| otherwise = Ekwg ps kasse :: Einkaufswagen→Int kasse (Ekwg ps) = sum (map cent ps) kassenbon :: Einkaufswagen→String kassenbon ew@(Ekwg ps) =

”Bob’ s Aulde Grocery Shoppe\n\n” ++

” Art ikel Menge Preis\n” ++

”−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−\n” ++

concatMap art ikel ps ++

”=====================================\n” ++

”Summe: ” ++ formatR 31 (showEuro ( kasse ew)) art ikel :: Posten→String art ikel p@( Posten a m) =

formatL 20 (show a) ++

formatR 7 (menge m) ++

formatR 10 (showEuro ( cent p)) ++ ” \n”

menge :: Menge→String menge ( Stueck n) = show n++ ” St”

menge (Gramm g) = show g++ ” g. ” menge ( Lit er l ) = show l++ ” l . ” formatL :: Int→String→String formatL n st r = take n ( st r++ replicat e n ’ ’ ) formatR :: Int→String→String formatR n st r =

take n ( replicat e (n−length st r ) ’ ’ ++ st r ) showEuro :: Int→String showEuro i =

show ( div i 100) ++ ” . ” ++

show (mod ( div i 10) 10) ++

show (mod i 10)++ ” EU”

inventur :: Lager→Int inventur ( Lager l ) = sum (map cent l )

Einkaufswagen Lager

Lager Posten Artikel

module Shoppe4 where import Data.Maybe

−−Modellierung der Artikel.

data Apfelsorte = Boskoop | CoxOrange | GrannySmith deriving (Eq, Show) apreis :: Apfelsorte→Int apreis Boskoop = 55 apreis CoxOrange = 60 apreis GrannySmith = 50 data Kaesesorte = Gouda | Appenzeller

deriving (Eq, Show) kpreis :: Kaesesorte→Double kpreis Gouda = 1450 kpreis Appenzeller = 2270 data Bio = Bio | Konv

deriving (Eq, Show) data Art ikel =

Apfel Apfelsorte | Eier

| Kaese Kaesesorte | Schinken

| Salami | Milch Bio deriving (Eq, Show) data Menge = Stueck Int | Gramm Int | Lit er Double

deriving (Eq, Show) type Preis = Maybe Int preis :: Art ikel→Menge→Preis preis ( Apfel a) ( Stueck n) = Just (n∗apreis a) preis Eier ( Stueck n)= Just (n∗20) preis (Kaese k)(Gramm g) = Just ( round( fromIntegral g∗1000∗kpreis k)) preis Schinken (Gramm g) = Just ( div (g∗199) 100) preis Salami (Gramm g)= Just ( div (g∗159) 100) preis ( Milch bio) ( Lit er l ) =

Just ( round ( l∗case bio of Bio→119; Konv→69)) preis = Nothing

−−Addition von Mengen addiere :: Menge→Menge→Menge addiere ( Stueck i ) ( Stueck j )= Stueck ( i + j ) addiere (Gramm g) (Gramm h) = Gramm (g+ h) addiere ( Lit er l ) ( Lit er m) = Lit er ( l + m) addiere m n = error (” addiere: ” ++ show m++ ” und ” ++ show n)

−−Posten:

data Posten = Posten Art ikel Menge deriving (Eq, Show) cent :: Posten→Int

cent ( Posten a m) = fromMaybe 0 ( preis a m)−−gibt keinen Laufzeitfehler!

−−Lagerhaltung:

data Lager = Lager [ Posten]

deriving (Eq, Show) leeresLager :: Lager leeresLager = Lager [ ]

suche :: Art ikel→Lager→Maybe Menge suche a ( Lager ps) =

listToMaybe [ m | Posten la m←ps,la == a ] einlagern :: Art ikel→Menge→Lager→Lager einlagern a m ( Lager ps) =

let hinein a m [ ] = [ Posten a m]

hinein a m ( Posten al ml: l )

| a == al= ( Posten a ( addiere m ml) : l )

| otherwise = ( Posten al ml: hinein a m l ) in case preis a m of

Nothing→Lager ps

→Lager ( hinein a m ps) data Einkaufswagen = Ekwg [ Posten]

deriving (Eq, Show) leererWagen :: Einkaufswagen leererWagen = Ekwg [ ]

einkauf :: Art ikel→Menge→Einkaufswagen→Einkaufswagen einkauf a m (Ekwg ps)

| isJust ( preis a m) = Ekwg ( Posten a m: ps)

| otherwise = Ekwg ps kasse :: Einkaufswagen→Int kasse (Ekwg ps) = sum (map cent ps) kassenbon :: Einkaufswagen→String kassenbon ew@(Ekwg ps) =

”Bob’ s Aulde Grocery Shoppe\n\n” ++

” Art ikel Menge Preis\n” ++

”−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−\n” ++

concatMap art ikel ps ++

”=====================================\n” ++

”Summe: ” ++ formatR 31 (showEuro ( kasse ew)) art ikel :: Posten→String art ikel p@( Posten a m) =

formatL 20 (show a) ++

formatR 7 (menge m) ++

formatR 10 (showEuro ( cent p)) ++ ” \n”

menge :: Menge→String menge ( Stueck n) = show n++ ” St”

menge (Gramm g) = show g++ ” g. ” menge ( Lit er l ) = show l++ ” l . ” formatL :: Int→String→String formatL n st r = take n ( st r++ replicat e n ’ ’ ) formatR :: Int→String→String formatR n st r =

take n ( replicat e (n−length st r ) ’ ’ ++ st r ) showEuro :: Int→String showEuro i =

show ( div i 100) ++ ” . ” ++

show (mod ( div i 10) 10) ++

show (mod i 10)++ ” EU”

inventur :: Lager→Int inventur ( Lager l ) = sum (map cent l )

PI3 WS 18/19 10 [42]

Refakturierung im Einkaufsparadies:

Modularchitektur

Artikel

Shoppe

Lager Einkaufswagen

Posten

PI3 WS 18/19 11 [42]

Refakturierung im Einkaufsparadies I: Artikel

I Es wirdallesexportiert I Reine Datenmodellierung module A r t i k e l where

data Apfelsorte = Boskoop | CoxOrange | GrannySmith apreis :: Apfelsorte → Int

data Kaesesorte = Gouda | Appenzeller kpreis :: Kaesesorte →Double

dataMenge = Stueck Int | Gramm Int | L i t e r Double addiere :: Menge→Menge→Menge

PI3 WS 18/19 12 [42]

Refakturierung im Einkaufsparadies II: Posten

modulePosten(

Posten , a r t i k e l , menge, posten , cent , hinzu )where

I Implementiert ADTPosten:

data Posten = Posten { a r t i k e l :: A r t i k e l , menge :: Menge }

I Konstruktor wirdnichtexportiert I Garantierte Invariante:

I Postenhat immer die korrekte Menge zu Artikel posten :: A r t i k e l→Menge→Maybe Posten posten a m =

case p r e i s a mof

Just _ → Just (Posten a m) Nothing →Nothing

PI3 WS 18/19 13 [42]

Refakturierung im Einkaufsparadies III: Lager

module Lager(

Lager , leeresLager , einlagern , suche , l i s t e , inventur ) where import A r t i k e l import Posten

I Implementiert ADTLager dataLager

I Signatur der exportierten Funktionen:

leeresLager :: Lager

einlagern :: A r t i k e l→Menge→ Lager→ Lager suche :: A r t i k e l→ Lager→Maybe Menge

l i s t e :: Lager→ [ ( Artikel , Menge) ] inventur :: Lager→ Int

I GarantierteInvariante:

I Lagerenthält keine doppelten Artikel

PI3 WS 18/19 14 [42]

Refakturierung IV: Einkaufswagen

moduleEinkaufswagen(

Einkaufswagen , leererWagen , einkauf , kasse , kassenbon ) where

IImplementiert ADTEinkaufswagen data Einkaufswagen = Ekwg [ Posten ] IGarantierte Invariante:

IKorrekte Menge zu Artikel im Einkaufswagen einkauf :: A r t i k e l→Menge

→ Einkaufswagen

→ Einkaufswagen einkauf a m (Ekwg ps ) =

case posten a mof Just p→ Ekwg (p : ps ) Nothing→Ekwg ps

INutzt dazu ADTPosten

PI3 WS 18/19 15 [42]

Refakturierung im Einkaufsparadies V: Hauptmodul

moduleShoppewhere import A r t i k e l import Lager import Einkaufswagen

I Nutzt andere Module l0= leeresLager

l1= einlagern ( Apfel Boskoop) (Stueck 1) l0 l2= einlagern Schinken (Gramm 50) l1 l3= einlagern (Milch Bio) ( L i t e r 6) l2 l4= einlagern ( Apfel Boskoop) (Stueck 4) l3 l5= einlagern (Milch Bio) ( L i t e r 4) l4 l6= einlagern Schinken (Gramm 50) l5

PI3 WS 18/19 16 [42]

(3)

Benutzung von ADTs

I OperationenundTypenmüssenimportiertwerden

I Möglichkeiten des Imports:

I Allesimportieren

I Nur bestimmteOperationen und Typenimportieren

I BestimmteTypen und Operationennichtimportieren

PI3 WS 18/19 17 [42]

Importe in Haskell

I Syntax:

import [qualified] M [ as N] [hiding] [ ( Bezeichner ) ] I Bezeichnergeben an,wasimportiert werden soll:

IOhne Bezeichner wirdallesimportiert

IMithidingwerden Bezeichnernichtimportiert

I Für jeden exportierten BezeichnerfausMwird importiert

I fundqualifizierterBezeichnerM. f

I qualified:nur qualifizierterBezeichnerM. f

IUmbenennung bei Import mitas(dannN. f)

IKlasseninstanzen und Typsynonyme werden immer importiert I Alle Importe stehen immer amAnfangdes Moduls

PI3 WS 18/19 18 [42]

Beispiel

moduleM(a , b) where. . .

Import(e) Bekannte Bezeichner

importM a,b,M. a,M. b

importM() (nothing)

importM(a) a,M. a

import qualifiedM M. a,M. b import qualifiedM() (nothing) import qualifiedM(a) M. a importMhiding () a,b,M. a,M. b importMhiding (a) b,M. b import qualifiedMhiding () M. a,M. b import qualifiedMhiding (a) M. b importM as B a,b,B. a,B. b

importM as B(a) a,B. a

import qualifiedM as B B. a,B. b

Quelle: Haskell98-Report, Sect. 5.3.4

PI3 WS 18/19 19 [42]

Ein typisches Beispiel

I Modul implementiert Funktion, die auch importiert wird I Umbenennung nicht immer praktisch

I Qualifizierter Import führt zulangenBezeichnern

I Einkaufswagenimplementiert Funktionen a r t i k e lundmenge, die auch ausPostenimportiert werden:

importPosten hiding ( a r t i k e l , menge) import qualified Posten as P( a r t i k e l , menge) a r t i k e l p =

formatL 20 (show (P. a r t i k e l p)) ++ formatR 7 (menge (P.menge p)) ++ formatR 10 (showEuro ( cent p)) ++ "\n"

PI3 WS 18/19 20 [42]

Schnittstelle vs. Implementation

I GleicheSchnittstellekann unterschiedlicheImplementationenhaben

I Beispiel: (endliche) Abbildungen

PI3 WS 18/19 21 [42]

Endliche Abbildungen

I Viel gebraucht, oft in Abwandlungen (Hashtables, Sets, Arrays) I Abstrakter Datentyp fürendliche Abbildungen:

IDatentyp dataMapα β

ILeere Abbildung:

empty :: Mapα β

IAbbildung auslesen:

lookup :: Ordα⇒α→Mapα β→Maybeβ

IAbbildung ändern:

i n s e r t :: Ordα⇒α→β→Mapα β→Mapα β

IAbbildung löschen:

delete :: Ordα⇒α→Mapα β→Mapα β

PI3 WS 18/19 22 [42]

Eine naheliegende Implementation

I Modellierung als Haskell-Funktion:

dataMapα β= Map (α→Maybeβ) I Damit einfacheslookup,i n s e r t,delete:

empty = Map (λx→ Nothing) lookup a (Map s ) = s a i n s e r t a b (Map s ) =

Map (λx→ i f x == athen Just b else s x) delete a (Map s ) =

Map (λx→ i f x == athenNothing else s x) I Instanzen von Eq, Shownicht möglich

I Speicherleck: überschriebene Zellen werden nicht freigegeben

Endliche Abbildungen: Anwendungsbeispiel

I Lager als endliche Abbildung:

dataLager = Lager (M.Map A r t i k e l Menge) I Artikel suchen:

suche :: A r t i k e l→Lager→Maybe Menge suche a (Lager l ) = M. lookup a l I Ins Lager hinzufügen:

einlagern :: A r t i k e l→Menge→Lager→Lager einlagern a m (Lager l ) =

caseposten a mof

Just _ →caseM. lookup a l of

Just q →Lager (M. i n s e r t a ( addiere m q) l ) Nothing→Lager (M. i n s e r t a m l )

Nothing→Lager l

I Für Inventur fehlt Möglichkeit zurIteration I Daher: Map alsAssoziativliste

(4)

Map als sortierte Assoziativliste

dataMapα β= Map { toList :: [ (α, β) ] } I Einfache Implementierung:

i n s e r t :: Ordα⇒α→β→Mapα β→Mapα β i n s e r t a v (Map s ) = Map ( i n s e r t ’ s )where

i n s e r t ’ [ ] = [ ( a , v ) ]

i n s e r t ’ s0@((b , w) : s ) | a> b = (b , w) : i n s e r t ’ s

| a == b = (a , v ) : s

| a< b = (a , v ) : s0 I Zusatzfunktionalität:

I Iteration (SelektortoList)

I Instanzen vonEqundShow(abgeleitet)

I . . . ist aberineffizient(Zugriff/Löschen inO(n)) I Deshalb:balancierte Bäume

PI3 WS 18/19 25 [42]

AVL-Bäume und Balancierte Bäume

AVL-Bäume

Ein Baum istausgeglichen, wenn I alle Unterbäume ausgeglichen sind, und

I der Höhenunterschied zwischen zwei Unterbäumen höchstens eins beträgt.

Balancierte Bäume

Ein Baum istbalanciert, wenn I alle Unterbäume balanciert sind, und I für den linken und rechten Unterbauml,rgilt:

size(l)w·size(r) (1)

size(r)w·size(l) (2)

wGewichtung(Parameter des Algorithmus)

PI3 WS 18/19 26 [42]

Implementation von balancierten Bäumen

I Der Datentyp data Treeα= Null

| Node Int (Treeα) α(Treeα) derivingEq I Gewichtung (Parameter des Algorithmus):

weight :: Int

I Hilfskonstruktor, setzt Größe (l,rbalanciert) node :: Tree α→α→Treeα→ Treeα I Selektor: Größe des Baumes (0 fürNull)

s i z e :: Tree α→ Int

PI3 WS 18/19 27 [42]

Implementation von balancierten Bäumen

I Hilfskonstruktor, balanciert ggf. neu aus:

mkNode :: Treeα→α→ Treeα→ Treeα

IVoraussetzungen:

I l,rbalanciert

IGesamtbaum “fast” balanciert:

size(l)−1 ≤ w·size(r) (3)

size(r)−1 ≤ w·size(l) (4)

IWird beim Löschen und Einfügen benutzt

PI3 WS 18/19 28 [42]

Balance sicherstellen

I Problem:

Nach Löschen oder Einfügen zu großes Ungewicht

I Lösung:

Rotierender Unterbäume

sx

sy sz

PI3 WS 18/19 29 [42]

Linksrotation

xt

yt zt

=⇒

xt yt

zt

r o t l :: Treeα→ Treeα

r o t l (Node _ xt y (Node _ yt x zt )) = node (node xt y yt ) x zt

PI3 WS 18/19 30 [42]

Rechtsrotation

xt yt

zt ⇒

xt

yt zt

r o t r :: Treeα→ Treeα

r o t r (Node _ (Node _ ut y vt ) x r t ) = node ut y (node vt x r t )

PI3 WS 18/19 31 [42]

Balanciertheit sicherstellen

I Fall 1: Äußerer Unterbaum zu groß I Lösung: Linksrotation

sx sy

sz

PI3 WS 18/19 32 [42]

(5)

Balanciertheit sicherstellen

I Fall 2: Innerer Unterbaum zu groß oder gleich groß

I Reduktion auf vorherigen Fall durch Rechtsrotation des Unterbaumes

sx sy

sz

sx sy

sz

⇒. . .

PI3 WS 18/19 33 [42]

Balance sicherstellen

I Hilfsfunktion:Balanceeines Baumes bias :: Treeα→ Ordering bias Null = EQ

bias (Node _ l t _ r t ) = compare ( s i z e l t ) ( s i z e r t ) I Zu implementieren:mkNode lt y rt

IVoraussetzung:l t,r tbalanciert

IKonstruiert neuen balancierten Baum mit Knoteny I Fallunterscheidung:

I r tzugroß, zweiUnterfälle:

ILinker Unterbaum vonr tkleiner (Fall 1):bias r t == LT

ILinker Unterbaum vonr tgrößer/gleich groß (Fall 2):bias r t == EQ, bias r t == GT

I l tzugroß, zweiUnterfälle(symmetrisch).

PI3 WS 18/19 34 [42]

Konstruktion eines ausgeglichenen Baumes

I Voraussetzung:l t,r tbalanciert mkNode :: Treeα→α→Treeα→ Treeα mkNode l t x r t

| l s + r s<2 = node l t x r t

| weight∗ l s <r s =

i f bias r t == LTthen r o t l (node l t x r t ) else r o t l (node l t x ( r o t r r t ))

| l s>weight∗ r s =

i f bias l t == GTthen r o t r (node l t x r t ) else r o t r (node ( r o t l l t ) x r t )

| otherwise = node l t x r t where l s = s i z e l t ; r s= s i z e r t

PI3 WS 18/19 35 [42]

Balancierte Bäume als Maps

I Endliche Abbildung: Bäume mit(key , value )Paaren I lookup ’liest Element aus:

lookup ’ :: Ordα⇒α→ Tree (α,β)→Maybeβ I i n s e r t ’fügt neues Element ein:

i n s e r t ’ :: Ordα⇒α→β→ Tree (α, β)→Tree (α, β) i n s e r t ’ k v Null = node Null (k , v) Null

i n s e r t ’ k v (Node n l a@(kn , _) r )

| k<kn = mkNode ( i n s e r t ’ k v l ) a r

| k == kn = Node n l (k , v) r

| k>kn = mkNode l a ( i n s e r t ’ k v r ) I remove ’löscht ein Element

IBenötigt Hilfsfunktion join :: Treeα→Treeα→Treeα

PI3 WS 18/19 36 [42]

Zusammenfassung Balancierte Bäume

I Verkapselung des Datentypen:

dataMapα β= Map { tree :: Tree (α, β) } i n s e r t :: Ordα⇒α→β→Mapα β→Mapα β i n s e r t k v (Map t ) = Map ( i n s e r t ’ k v t )

I Auslesen, einfügen und löschen: logarithmischer Aufwand (O(logn)) I Fold: linearer Aufwand (O(n))

I Guten durchschnittlichen Aufwand

I Auch in der Haskell-Bücherei:Data .Map(mit vielen weiteren Funktionen)

PI3 WS 18/19 37 [42]

Benchmarking: Setup

I Wieschnellsind die Implementationenwirklich?

I Benchmarking: nicht trivial

IVerzögerte Auswertung und optimierender Compiler

IMessen wir dasrichtige?

IBenchmarking-Tool: Criterion

I Setup:Map Int Stringmit 50000 zufälligen Einträgen erzeugen I Darin:

IEinmal zufällig lesen (lookup), schreiben (i n s e r t), löschen (delete)

ISequenz aus fünfmal löschen und schreiben, zweihundertmal lesen (mixed)

PI3 WS 18/19 38 [42]

Benchmarking: Resultate

create lookup i n s e r t delete mixed (1) 358.4 ms

7.483 ms

2.66 ms 134.70µs

10.75 ns 159.70 ps

10.90 ns 170.90 ps

1.83 ms 111.80µs (2) 6.20 s

37.59 ms

11.57µs 351.3 ns

133.8µs 2.36µs

148.40µs 1.99µs

5.67 ms 128.10µs (3) 470.00 ms

2.69 ms

265.10 ns 4.54 ns

138.90µs 2.35µs

137.60µs 3.00µs

2.18 ms 81.68µs (4) 392.7 ms

5.02 ms

189.2 ns 13.41 ns

135.7µs 2.00µs

134.50µs 3.10µs

2.08 ms 80.22µs

(1)MapFun, (2)MapList, (3)MapWeighted, (4)Data .Map. Lazy Einträge: durchschnittl. Ausführungszeit, Standardabweichung

Defizite von Haskells Modulsystem

I Signatur ist nurimplizit

IExportliste enthält nur Bezeichner

IWünschenswert: Signatur an der Exportliste annotierbar, oder Signaturen in separater Datei

IIn Java:Interfaces

I Klasseninstanzen werdenimmerexportiert.

I KeinPaket-System

(6)

ADTs vs. Objekte

I ADTs (Haskell):TypplusOperationen I Objekte (z.B. Java):Interface,Methoden.

I Gemeinsamkeiten:

I Verkapselung(information hiding) der Implementation I Unterschiede:

I Objekte habeninternen Zustand, ADTs sindreferentiell transparent;

I Objekte habenKonstruktoren, ADTs nicht (Konstruktoren nicht unterscheidbar)

I Vererbungsstrukturauf Objekten (Verfeinerungfür ADTs)

I Java:interfaceeigenes Sprachkonstrukt

I Java:packagesfür Sichtbarkeit

PI3 WS 18/19 41 [42]

Zusammenfassung

I Abstrakte Datentypen(ADTs):

IBesteht ausTypenundOperationendarauf

I Realisierung in Haskell durchModule

I Beispieldatentypen: endliche Abbildungen

I Nächste Vorlesung: ADTs durchEigenschaftenspezifizieren

PI3 WS 18/19 42 [42]

Referenzen

ÄHNLICHE DOKUMENTE

I Einkaufswagen implementiert Funktionen artikel und menge, die auch aus Posten importiert werden:. import Posten hiding (artikel, menge) import qualified Posten as P(artikel,

I Werte des Typen können nur über die bereitgestellten Operationen erzeugt werden. I Eigenschaften von Werten des Typen werden nur über die bereitgestellten

I Werte des Typen können nur über die bereitgestellten Operationen erzeugt werden. I Eigenschaften von Werten des Typen werden nur über die bereitgestellten

Ein abstrakter Datentyp (ADT) besteht aus einem (oder mehreren) Typen und Operationen darauf, mit folgenden Eigenschaften:. I Werte des Typen können nur über die

Als Chirurg hatte Moier einen bedeutenden Ruf in den Ostseeprovinzen. Zu Operationen entschloß er sich un- gern. Halbe Jahre lang warteten zuweilen Staarblinde in der Klinik auf den

● neben Steuerkreuz 6 Buttons (4 Buttons mehr als für unser

Aufteilung der positiven und negativen Halbwellen auf zwei Transistoren beide Transistoren, wenn komplement¨ ar, in Kollektorschaltung Arbeitspunkte werden durch

Auch gehören unsere Typen ganz der Periode der feinsten und reichsten Blüthe des attischen Grabreliefs an (eingeschlossen das Original der Gruppe des Künstlers