• Keine Ergebnisse gefunden

Algebraische Datentypen

N/A
N/A
Protected

Academic year: 2022

Aktie "Algebraische Datentypen"

Copied!
5
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Praktische Informatik 3: Funktionale Programmierung Vorlesung 3 vom 01.11.2016: Algebraische Datentypen

Christoph Lüth Universität Bremen Wintersemester 2016/17

16:02:22 2017-01-17 1 [35]

Fahrplan

I Teil I: Funktionale Programmierung im Kleinen

IEinführung

IFunktionen und Datentypen

I Algebraische Datentypen

ITypvariablen und Polymorphie

IFunktionen höherer Ordnung I

IFunktionen höherer Ordnung II und Effizenzaspekte I Teil II: Funktionale Programmierung im Großen I Teil III: Funktionale Programmierung im richtigen Leben

PI3 WS 16/17 2 [35]

Inhalt

I RekursiveDatentypen

I RekursiveDefinition

I . . . und wozu sie nützlich sind

I Rekursive Datentypen in anderen Sprachen

I Fallbeispiel: Labyrinth

PI3 WS 16/17 3 [35]

Algebraische Datentypen

data T = C1t1,1 . . .t1,k1

| C2t2,1 . . .t2,k2

...

| Cntn,1 . . .tn,kn

I Aufzählungen

I Konstrukturen miteinemodermehrerenArgumenten (Produkte) I Der allgemeine Fall:mehrereKonstrukturen

Heute:Rekursion

PI3 WS 16/17 4 [35]

Der Allgemeine Fall: Algebraische Datentypen

data T = C1t1,1. . .t1,k1

| C2t2,1. . .t2,k2

...

| Cntn,1. . .tn,kn

Drei Eigenschaften eines algebraischen Datentypen 1.KonstruktorenC1, . . . ,Cnsinddisjunkt:

Cix1. . .xn= Cjy1. . .ym=⇒i=j 2.Konstruktorensindinjektiv:

C x1. . .xn= C y1. . .yn=⇒xi= yi 3.Konstruktorenerzeugenden Datentyp:

∀x∈T.x= Ciy1. . .ym

Diese Eigenschaften machenFallunterscheidungwohldefiniert.

PI3 WS 16/17 5 [35]

Algebraische Datentypen: Nomenklatur

data T = C1t1,1. . .t1,k1

...

| Cntn,1. . .tn,kn I CisindKonstruktoren

IImmervordefiniert

I Selektorensind Funktionen seli,j: seli,j :: T→ti,ki

seli,j(Citi,1. . .ti,ki) = ti,j ILinksinvers zu Konstruktor Ci, partiell

IKönnenvordefiniert werden (erweiterte Syntax derdataDeklaration) I Diskriminatorensind Funktionen disi:

disi :: T→Bool disi(Ci. . .) = True disi_ = False

IDefinitionsbereichsbereich des Selektors seli,nievordefiniert

PI3 WS 16/17 6 [35]

Rekursive Datentypen

I Der definierte TypTkannrechtsbenutzt werden.

I Rekursive Datentypen definierenunendlich großeWertemengen.

I ModelliertAggregation(Sammlung von Objekten).

I Funktionen werden durchRekursiondefiniert.

Uncle Bob’s Auld Time Grocery Shoppe Revisited

I Das Lager für Bob’s Shoppe:

Iist entweder leer,

Ioder es enthält einen Artikel und Menge, und weiteres.

dataLager = LeeresLager

| Lager A r t i k e l Menge Lager

(2)

Suchen im Lager

I Rekursive Suche (erste Version):

suche :: A r t i k e l→ Lager→Menge suche art LeeresLager = ???

I Modellierung desResultats:

data Resultat = Gefunden Menge | NichtGefunden I Damit rekursiveSuche:

suche :: A r t i k e l→ Lager→ Resultat suche art (Lager l a r t m l )

| art == l a r t = Gefunden m

| otherwise = suche art l

suche art LeeresLager = NichtGefunden

PI3 WS 16/17 9 [35]

Einlagern

I Mengen sollen aggregiert werden (35l Milch + 20l Milch = 55l Milch) I Dazu Hilfsfunktion:

addiere (Stueck i ) (Stueck j )= Stueck ( i + j ) addiere (Gramm g) (Gramm h) = Gramm (g+ h) addiere ( L i t e r l ) ( L i t e r m) = L i t e r ( l +m)

addiere m n = er ro r (" addiere : ␣"++ show m++ "␣und␣"++ show n) I Damit einlagern:

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

| a == a l = Lager a ( addiere m ml) l

| otherwise = Lager a l ml ( einlagern a m l ) I Problem: Falsche Mengenangaben

Iz.B.einlagern Eier ( L i t e r 3.0) l

PI3 WS 16/17 10 [35]

Einlagern (verbessert)

I Eigentliche Funktioneinlagernwird alslokale Funktionversteckt, und nur mit gültiger Mengenangabe aufgerufen:

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

let einlagern ’ a m LeeresLager = Lager a m LeeresLager einlagern ’ a m (Lager a l ml l )

| a == a l = Lager a ( addiere m ml) l

| otherwise = Lager a l ml ( einlagern ’ a m l ) in case p r e i s a mof

Ungueltig → l _→ einlagern ’ a m l

PI3 WS 16/17 11 [35]

Einkaufen und bezahlen

I Wir brauchen einenEinkausfwagen:

dataEinkaufswagen = LeererWagen

| Einkauf A r t i k e l Menge Einkaufswagen I Artikel einkaufen:

einkauf :: A r t i k e l→Menge→ Einkaufswagen→Einkaufswagen einkauf a m e =

case p r e i s a mof Ungueltig → e _→ Einkauf a m e I Gesamtsumme berechnen:

kasse :: Einkaufswagen→ Int kasse LeererWagen = 0

kasse ( Einkauf a m e) = cent a m+ kasse e

PI3 WS 16/17 12 [35]

Beispiel: Kassenbon

kassenbon :: Einkaufswagen→ String Ausgabe:

Bob’s Aulde Grocery Shoppe

Artikel Menge Preis

---

Schinken 50 g. 0.99 EU

Milch Bio 1.0 l. 1.19 EU

Schinken 50 g. 0.99 EU

Apfel Boskoop 3 St 1.65 EU

=====================================

Summe: 4.82 EU

Unveränderlicher Kopf

Ausgabe von Artikel und Mange (rekur- siv)

Ausgabe vonkasse

PI3 WS 16/17 13 [35]

Kassenbon: Implementation

I Kernfunktion:

a r t i k e l :: Einkaufswagen→ String a r t i k e l LeererWagen = ""

a r t i k e l ( Einkauf a m e) = formatL 20 (show a) ++ formatR 7 (menge m) ++

formatR 10 (showEuro ( cent a m)) ++ "\n"++ a r t i k e l e

I Hilfsfunktionen:

formatL :: Int→ String→ String

PI3 WS 16/17 14 [35]

Rekursive Typen in imperativen Sprachen

PI3 WS 16/17 15 [35]

Rekursive Typen in Java

I Nachbildung durch Klassen, z.B. für Listen:

class L i s t {

public L i s t (Object el , L i s t t l ) { this. elem= e l ;

this. next= t l ; }

public Object elem ; public L i s t next ; I Länge (iterativ):

int length () { int i= 0;

for ( L i s t cur=this; cur !=null; cur= cur . next ) i ++ ;

return i ; }

PI3 WS 16/17 16 [35]

(3)

Rekursive Typen in C

I C: Produkte, Aufzählungen, keine rekursiven Typen I Rekursion durchZeiger

typedef struct l i s t _ t { void ∗elem ; struct l i s t _ t ∗next ; }∗l i s t ;

I Konstruktorennutzerimplementiert l i s t cons(void ∗hd , l i s t t l ) { l i s t l ;

i f (( l= ( l i s t ) malloc (sizeof(struct l i s t _ t )))== NULL) { p r i n t f ( "Out␣of␣memory\n" ) ; e x i t (−1);

}

l→elem= hd ; l→ next= t l ; return l ;

}

PI3 WS 16/17 17 [35]

Fallbeispiel

PI3 WS 16/17 18 [35]

Fallbeispiel: Zyklische Datenstrukturen

Quelle: docs.gimp.org

PI3 WS 16/17 19 [35]

Modellierung eines Labyrinths

I EingerichtetesLabyrinth ist entweder

Ieine Sackgasse,

Iein Weg, oder

Ieine Abzweigung in zwei Richtungen.

dataLab = Dead Id

| Pass Id Lab

| TJnc Id Lab Lab

I Ferner benötigt: eindeutigeBezeichnerder Knoten type Id = Integer

PI3 WS 16/17 20 [35]

Ein Labyrinth (zyklenfrei)

0 1 2 3 4

5?

6 7?

8 6

-9 6

10?

-11 12 -13 6

14?

15 16

? -17

6

18 -19

20 6

21 22? -23

6 24?

PI3 WS 16/17 21 [35]

Traversion des Labyrinths

I Ziel:Pfadzu einem gegebenZielfinden

I BenötigtPfadeundTraversion dataPath = Cons Id Path

| Mt dataTrav = Succ Path

| F a i l

PI3 WS 16/17 22 [35]

Traversionsstrategie

I Geht vonzyklenfreienLabyrinth aus

I An jedem Knoten prüfen, ob Ziel erreicht, ansonsten

I an SackgasseF a i l

I an Passagen weiterlaufen

I an Kreuzungen Auswahl treffen I Erfordert Propagation vonF a i l:

cons :: Id→Trav→ Trav s e l e c t :: Trav→Trav→ Trav

Zyklenfreie Traversion

traverse1 :: Id→Lab→Trav traverse1 t l

| nid l == t = Succ (Cons ( nid l ) Mt)

| otherwise =case l of Dead _→ F a i l

Pass i n→ cons i ( traverse1 t n)

TJnc i n m→ s e l e c t (cons i ( traverse1 t n)) (cons i ( traverse1 t m)) I Wie mit Zyklen umgehen?

I An jedem Knoten prüfen ob schon im Pfad enthalten

(4)

Traversion mit Zyklen

I VeränderteStrategie: Pfad bis hierher übergeben

I Pfad musshintenerweitert werden.

I WennaktuellerKnoten in bisherigen Pfadenthaltenist,F a i l I Ansonsten wie oben

I Neue Hilfsfunktionen:

contains :: Id→Path→ Bool snoc :: Path→ Id→ Path

PI3 WS 16/17 25 [35]

Traversion mit Zyklen

traverse2 :: Id→Lab→Path→ Trav traverse2 t l p

| nid l == t = Succ (snoc p ( nid l ))

| contains ( nid l ) p = F a i l

| otherwise =case l of Dead _→ F a i l

Pass i n→ traverse2 t n (snoc p i )

TJnc i n m→ s e l e c t ( traverse2 t n (snoc p i )) ( traverse2 t m (snoc p i ))

PI3 WS 16/17 26 [35]

Ein Labyrinth (mit Zyklen)

0 1 2 3 4

5?

∗ 6 7? 8

6 -9

6

10?

-11 12 -13 6

14?

15

∗6 16?

-17 6

18 -19

20 6

21 22? -23

6 24?

PI3 WS 16/17 27 [35]

Ungerichtete Labyrinth

I In einemungerichtetenLabyrinth haben Passagen keine Richtung.

ISackgassen haben einen Nachbarn,

Ieine Passage hat zwei Nachbarn,

Iund eine Abzweigung drei Nachbarn.

dataLab = Dead Id Lab

| Pass Id Lab Lab

| TJnc Id Lab Lab Lab

I Andere Datentypen und Hilfsfunktionen bleiben (mutatis mutandis) I Jedes nicht-leere ungerichtete Labyrinth hatZyklen.

I Invariante(nicht durch Typ garantiert)

PI3 WS 16/17 28 [35]

Traversion in ungerichteten Labyrinthen

I Traversionsfunktion wie vorher traverse3 :: Id→ Lab→ Path→Trav traverse3 t l p

| nid l == t = Succ (snoc p ( nid l ))

| contains ( nid l ) p = F a i l

| otherwise =case l of

Dead i n→ traverse3 t n (snoc p i )

Pass i n m→ s e l e c t ( traverse3 t n (snoc p i )) ( traverse3 t m (snoc p i )) TJnc i n m k→ s e l e c t ( traverse3 t n (snoc p i ))

( s e l e c t ( traverse3 t m (snoc p i )) ( traverse3 t k (snoc p i )))

PI3 WS 16/17 29 [35]

Zusammenfassung Labyrinth

I Labyrinth−→GraphoderBaum I In Haskell: gleicher Datentyp I Referenzen nichtexplizitin Haskell

IKeineundefiniertenReferenzen (erhöhteProgrammsicherheit)

IKeineGleichheitauf Referenzen

IGleichheit istimmerstrukturell (oderselbstdefiniert)

PI3 WS 16/17 30 [35]

Beispiel: Zeichenketten selbstgemacht

I EineZeichenketteist

I entwederleer(das leere Wort)

I oder einZeichencund eine weitereZeichenkettexs data MyString = Empty

| Cons Char MyString

I LineareRekursion

I Genau ein rekursiver Aufruf

PI3 WS 16/17 31 [35]

Rekursive Definition

I Typisches Muster:Fallunterscheidung

IEinFallproKonstruktor

I Hier:

ILeereZeichenkette

INichtleereZeichenkette

PI3 WS 16/17 32 [35]

(5)

Funktionen auf Zeichenketten

I Länge:

len :: MyString→ Int

len Empty = 0

len (Cons c s t r ) = 1+ len s t r I Verkettung:

cat :: MyString→ MyString→MyString cat Empty t = t

cat (Cons c s ) t = Cons c ( cat s t ) I Umkehrung:

rev :: MyString→ MyString rev Empty = Empty

rev (Cons c t ) = cat ( rev t ) (Cons c Empty)

PI3 WS 16/17 33 [35]

Was haben wir gesehen?

I StrukturellähnlicheTypen:

I Einkaufswagen,Path,MyString(Listen-ähnlich)

I Resultat,Preis,Trav(Punktierte Typen) I ÄhnlicheFunktionendarauf

I Besser:eineTypdefinition mit Funktionen, Instantiierung zu verschiedenen Typen

−→Nächste Vorlesung

PI3 WS 16/17 34 [35]

Zusammenfassung

I Datentypen könnenrekursivsein

I Rekursive Datentypen sindunendlich(induktiv) I Funktionen werdenrekursivdefiniert

I Fallbeispiele: Einkaufen in Bob’s Shoppe, Labyrinthtraversion I Viele strukturell ähnliche Typen

I NächsteWoche: Abstraktion über Typen (Polymorphie)

PI3 WS 16/17 35 [35]

Referenzen

ÄHNLICHE DOKUMENTE

I Funktionen höherer Ordnung II und Effizenzaspekte I Teil II: Funktionale Programmierung im Großen I Teil III: Funktionale Programmierung im richtigen Leben. PI3 WS 16/17

Praktische Informatik 3: Funktionale Programmierung Vorlesung 5 vom 15.11.2016: Funktionen Höherer Ordnung I..

I Eine Funktion hat ein Speicherleck, wenn Speicher unnötig lange im Zugriff bleibt. I “Echte” Speicherlecks wie in C/C++

I Striktheit: Speicherlecks vermeiden (bei verzögerter Auswertung) I Vorteil: Effizienz muss nicht im Vordergrund stehen. PI3 WS 16/17

I Klasseninstanzen und Typsynonyme werden immer importiert I Alle Importe stehen immer am Anfang des Moduls. PI3 WS 16/17 16 [37].. Java):

I Funktionen höherer Ordnung II und Effizenzaspekte I Teil II: Funktionale Programmierung im Großen I Teil III: Funktionale Programmierung im richtigen Leben.. PI3 WS 16/17

Praktische Informatik 3: Funktionale Programmierung Vorlesung 5 vom 11.11.2014: Funktionen Höherer Ordnung I.. Christoph Lüth Universität Bremen

Praktische Informatik 3: Funktionale Programmierung Vorlesung 6 vom 18.11.2014: Funktionen Höherer Ordnung II..