Standardparadigmen: Deklarative Sprachen

Werbung
Teil 3
Standardparadigmen:
Deklarative Sprachen



funktionales Programmieren: Lisp 1.5
logisches Programmieren: Prolog
relationales Programmieren: Datalog
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
1
Lisp 1.5
Urform von Lisp (und aller funktionaler Sprachen)
 Datenstruktur: Listen (eigentlich Bäume), Atome
 keine Operationen auf Atomen außer Vergleich, Test
 Programme sind symbolische Ausdrücke S (S-Ausdrücke), repräsentiert als Listen
 Programme zur Laufzeit modifizierbar
·
Atom: Zeichenreihe z ∈ S, spezielle Zeichenreihe nil ∈ S,
x
·
Baum: x,y ∈ S: cons [x,y] = (x . y) ∈ S
x
Liste: [x1,x2,x3,...,xn] = (x1 x2 x3 ... xn ) = (x1 . (x2 . (x3 . (...(xn . nil)...) 1
·
·
leere Liste : [ ] = nil
2
Funktionen zur Manipulation von Listen und Atomen:
x
···
atom, eq, car, cdr, cons
3
·
Grundoperationen:
 [[lambda ,x], y] = ((lambda x) y) entspricht λx .y
 (quote x) = 'x entspricht Zeichenreihe x (nicht der Term x!)
xn
 (label n x) entspricht n = x

( cond (x1,y1), (x2,y2),..., (xn,yn)) entspricht if x1≠nil then y1 else (cond (x2,y2),...,(xn,yn))
y
x
Interpretierer eval berechnet symbolische Ausdrücke durch α-, β-, η−Konversion
Literatur:
 John McCarthy: Comm. of the ACM 3(1960), Nr. 4, 184-195
 McCarthy et al.: Lisp 1.5 Programmer's Manual. MIT Press 1965

Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
2
nil
Grundfunktionen
t bezeichnet beliebigen Wert ≠ nil (nil falsch, t wahr)
atom: S → BOOL
atom [(x . y)]= nil
 atom [X] = t
eq: Atom × Atom → BOOL
eq [X,Y] = nil
 eq [X,X] = t
car: S → S
 car [(x . y)] = x
cdr: S → S
 cdr [(x . y)] = y
cons: S × S → S
 cons[x,y] = (x . y)
Alle nicht angegebenen Fälle liefern nil, insbesondere eq angewandt auf Listen
Lisp 1 war die erste verbreitete Sprache mit automatischer Speicherbereinigung!
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
3
Emacs Lisp
LaTeX-Filter
(find-file (getenv "INFILE"))
(replace-string "
" "§NeueZeile§" nil)
(beginning-of-buffer)
(replace-string "§NeueZeile§ §NeueZeile§" "§Absatz§" nil)
(beginning-of-buffer)
(replace-regexp "\\\\cite{[^#]*}" "" nil) (beginning-of-buffer)
...
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
4
Emacs Lisp
Türme von Hanoi
(defun hanoi (n von nach zwischen)
(cond ((< n 1) ; fertig
(t (hanoi (n-1) von zwischen nach)
(move von nach)
(hanoi (n-1) zwischen nach von)))
)
(defun show-move (von nach) ... )
(provide hanoi)
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
5
Der Sündenfall: Zuweisungen in Lisp
Alle heutigen Versionen von Lisp (Emacs Lisp, Scheme, Common Lisp, ...)
erlauben Zuweisungen:
Variablenvereinbarung (in Emacs Lisp):
(defvar variable)
oder
(defvar variable anfangswert)
oder
(defvar variable anfangswert ''Dokumentation'')
Zuweisung:
(setq variable wert)
Bedeutung:
variable zeigtHöhere
aufProgrammiersprachen
wert (keine
Kopie!)
Prof. Dr. Gerhard Goos
SS 2001
6
Grundprinzipien funktionaler
Sprachen










Berechnungsmodell: Reduktion von Ausdrücken wie in Lisp
Programm ist Folge von Funktionsdefinitionen und ein Ausdruck
Schreibweise angelehnt an übliche mathematische Schreibweisen
Programm und Daten getrennt
Grundtypen: Listen, Terme, übliche Grundtypen (Bool, Int, ...);
darauf aufbauend reichhaltiger Typverband
starke Typisierung, Verwendung von Typinferenz
mehrere Definitionen des gleichen Funktionsbezeichners möglich,
Auswahl der Funktionsdefinition bei Anwendung durch
Typinferenz und Durchmustern der Parameterlisten, um die erste
auf die Argumente zutreffende Definition zu finden: Durchmustern
in der Reihenfolge des Aufschreibens
zentraler Unterschied zwischen Sprachen: strikte (ML) und
faule (Haskell, Gofer) Auswertung von Argumenten
unterschiedlich gestaltete Modulkonzepte
parametrische Polymorphie
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
7
ML, Haskell und Gofer
Türme von
Hanoi
move 1 i j k = i ++
move n i j k =
(move (n-1) i
i ++ "-->" ++
(move (n-1) j
"-->" ++ k ++ "\n"
k j) ++
k ++ "\n"
i k)
++
hanoi 0 = "Ja Ja!"
hanoi n = move n "A" "B" "C"
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
8
Konstanten als Listen
Integer





addr xs [] [] = xs
addr [] ys [] = ys
addr xs [] "1" = addr xs "1" []
addr [] ys "1" = addr ys "1" []
addr ('0':xs) ('0':ys) []=
concat ["0", (addr xs ys [])]
addr ('0':xs) ('1':ys) []=
concat ["1", (addr xs ys [])]
...
addr ('1':xs) ('1':ys) "1" =
concat ["1", (addr xs ys "1")]
add x y =
reverse (addr(reverse x)(reverse y)[])
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
9
Konstanten als Funktionen höherer
Ordnung
Boolean






wahr t f = t
falsch t f = f
if-then-else b t f = b t f
und a b = if-then-else a
(if-then-else b wahr falsch)
falsch
oder a b = if-then-else a
wahr
(if-then-else b wahr falsch)
nicht a = if-then-else a falsch wahr
xoder a b = if-then-else a
(if-then-else b falsch wahr)
(if-then-else b wahr falsch)
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
10
Konstanten als Funktionen höherer
Ordnung
Integer








bit '0' = falsch bit '1' = wahr
tib a = ifthenelse a '1' '0'
plus x y z = xoder (xoder x y) z
ueber x y z = oder(und x z)(oder(und x y)(und y z))
addr xs [] '0' = xs
...
addr [] ys '1' = addr ys "1" '0'
addr (x:xs) (y:ys) z = concat [
[(tib(plus (bit x)(bit y)(bit z)))],
(addr xs ys (tib(ueber(bit x)(bit y)(bit z))))]
add x y=reverse(addr(reverse x)(reverse y)'0')
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
11
Anwendung Funktionen höherer
Ordnung
Faltung
Linksfaltung ( f , x , ( y1 , y2 , ... , yn-1 , yn,) ) =
f ( f ( ... f ( f ( x , y1 ) , y2 ) ... ) , yn-1) , yn)
foldl f x [] = x
foldl f x (y:ys) = foldl f (f x y) ys
sum = foldl (+) 0
product = foldl ( ) 1
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
12
Abstrakte Datentypen
Konstruktoren:
 data X = Konstr_1 | ... | Konstr_n
Operationen:
 op_1:: X-> Typ_1_1->...-> Typ_1_k
...
op_m:: X-> Typ_m_1->...-> Typ_m_l
Axiome:
 op_1 = ... op_m = ...
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
13
ADT Keller
data IntKeller =
EmptyStack |
Push (Int, IntKeller)
isEmpty :: IntKeller -> Bool
top :: IntKeller -> Int
pop :: IntKeller -> IntKeller
isEmpty EmptyStack = True
isEmpty Push (Int, s) = False
top Push (i s) = i
pop Push (i s) = s
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
14
Polymorphie
Parametrische Polymorphie
data Stack t = EmptyStack
Push (t, Stack t)
istLeer :: Stack t -> Bool
top :: Stack t -> t
pop :: Stack t -> Stack t
isEmpty EmptyStack = True
isEmpty Push (i, s) = False
top Push (i s) = i
pop Push (i s) = s
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
15
Typisierung
Einsetzen eines Typs in die Typvariable ergibt neuen Typ
Muß konsistent sein
Typ Stack Int:
Push ( 1 Push ( 2 Push ( 3 Empty )))
Typ - Fehler:
Push ( 1 Push ( True Push ( 3 Empty )))
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
16
Dynamisch vs Statisch
Typanalyse zur Laufzeit:
 Berechnet den konkreten Typ jedes Terms
 Beispiel Lisp.
Typanalyse zur Übersetzungszeit:
 Typinferenz
 Berechnet den allgemeinsten Typ jedes Terms im gegebenen Typverband
 Beispiel Haskell, ML, Gofer.
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
17
Prolog
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
18
Entscheidbarkeit
Unentscheidbar:
 Gültigkeit prädikatenlogischer Formeln
 Erfüllbarkeit prädikatenlogischer Formeln
Semi-entscheidbar:
 Unerfüllbarkeit prädikatenlogischer Formeln
 Algorithmus terminiert, wenn Formel nicht erfüllbar
 Resolution, Substitution und Unifikation
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
19
Grundresolution
Klauseln K disjunktiv verknüpfte Literal
F = ∀x1, ... , xn F*
Ki = P1 ∨ P2 ∨ ... ∨ Pm
F* = K1 ∧ K2 ∧ ... ∧ Kn
F ist unerfüllbar gdw. K1 , K2 , ... , Kt mit

Kt ist leere Klausel
Ki< t Grundinstanz
K ∈ F*, Ki = K[x1/t1][x2/t2] ...[xn/tn] | t1, ... ,tn ∈ D(F)

Ki<t aussagenlogische Resolvente von Ka<i , Kb<i

Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
20
Problem
Grundsubstitution nicht vorausschauend
Gierig und daher ineffizient
Minimale Substitution für Resolutionsschritt
 Allgemeiner Unifikator
 Prädikatenlogische Resolution
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
21
Allgemeinster Unifikator
Substitution s ist Unifikator einer Menge L von Literalen { L1, L2, ... ,Lk } wenn
L1s = L2s = ... = Lks
Allgemeinster Unifikator s falls sub = s sub´
s
sub'
sub
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
22
Unifikation
Eingabe L
s:=[]
while |Ls| > 1 do
Finde in Ls Literale L1, L2 die unterschiedlich in Zeichen x, y
if keine Variablen x, y then Ausgabe „Nicht unifizierbar“
else Sei x Variable und y beliebiger Term
if x kommt vor in y then Ausgabe „Nicht unifizierbar“
else s:=s[x/y]
od
Ausgabe s
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
23
Prolog
Hornklauselprogramme
 Tatsachen: T(...).
 Prozedur: P(...) :- Q1 (...), Q2 (...), ... , Qn(...).
 Ziel: ?- Q1 (...), Q2 (...), ... , Qn(...).
Ergebnis eindeutig?
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
24
Beispiel
(1)
(2)
(3)
Frage
Q(x,z):-Q(y,z),R(x,y).
Q(x,x).
R(b,c).
?-Q(x,c)
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
25
Mögliche SLD Resolutionen
?-Q(x,c)
(1)
(2)
?-Q(y,c),R(x,y)
(1)
Q(c,c)
(2)
?-Q(y,c),R(v,x),R(x,y)
?-R(x,c)

(1)
(3)
(2)
?-R(v,x),R(x,c)
Q(b,c)
(3)
?-R(c,c)
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
26
Auswertestrategie
Deterministisch
Tiefensuche
 Nicht vollständig
 Endlosschleifen möglich
 Breitensuche vollständig
Kein „occur check“
Prozedurale Auswertung
Ausgabe weiterer Lösungen
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
27
Cut
Beispiel Hilfs-not Operator
not(X) :- X, !, fail.
not(_).
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
28
Türme von Hanoi
:- use_module(library(lineio)).
hanoi(N):- N >=0, move(N,"A","B","C").
move(0,_,_,_) :- !.
move(1,A,B,_) :put_chars(A),put_chars(" -> "),
put_chars(B), nl, !.
move(N,A,B,C) :- is(NN,N-1),
move(NN,A,C,B),
move(1,A,B,C),
move(NN,C,B,A).
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
29
Arithmetik Operatoren
pow(1,_,1).
pow(_,0,1).
pow(B,E,X):-is(EE,E-1),
pow(B,EE,Y),mul(B,Y,X).
mul(_,0,0):- !.
mul(0,_,0).
mul(A,B,X):- A < 0,is(AA,-A),
mul(AA,B,Y), is(X,-Y).
mul(A,B,X):- A > 0,is(AA,A-1),
mul(AA,B,Y), is(X,B+Y).
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
30
Flieger
:- assert(fz(Fliege)).
flugzeug(F):- fz(F).
flugzeug(F):put_chars("Ist ein(e)"),write(F),put_chars("ein Flugzeug?"),
get_line(L), L=="j",assert(fz(F)).
flugzeuge(FS):- findall(F,fz(F),FS).
flugzeuge:-flugzeuge(FL),zeige_fz(FL).
zeige_fz([]):- put_line("gibt keine!"), !.
zeige_fz([F]):- put_chars("Ein(e) "),
write(F), put_line("ist ein Flugzeug"),!.
zeige_fz([F FS]):-zeige_fz([F]),zeige_fz(FS).
?- flugzeuge.
Ein(e) fliege ist ein Flugzeug
yes
?- flugzeug(Maus).
Ist ein(e) Maus ein Flugzeug? j
yes
?- flugzeuge.
Ein(e) Fliege ist ein Flugzeug!
Ein(e) Maus ist ein Flugzeug!
yes
?- flugzeuge(L).
= [Fliege,Maus
] Höhere Programmiersprachen SS 2001
Prof. L
Dr. Gerhard
Goos
31
Datalog: Brücke logisches Programmieren relationale Algebra
Einsicht:
 Fakten p(t1,...,tn) definieren Relation p (im Sinne relationaler Algebra)


Voraussetzung: für ti nur Konstante oder Variable erlaubt, also nicht f(t'1,...,t'n)
Klauseln q(...) :- q1(...),...,qm(...) definieren Implikation zwischen Relationen
Datalog: die Sprache deduktiver Datenbanken: wie Prolog, aber mit Einschränkungen:
 Fakten und Implikationsklauseln definieren disjunkte Relationen F ∩ P= ∅
 Keine Funktionssymbole, nur Variable und Konstante als Argumente in Prädikaten
 Hornklausel ist logische Beziehung, keine implizite Ablaufsteuerung wie in Prolog
 alle Klauseln sind sicher:
Sichere Klausel: All-Quantifizierung der Variablen begrenzt auf Konstante in Fakten:
 Variable X heißt begrenzt, wenn sie vorkommt in:

benutzerdefiniertem Faktum oder in Form X=a, a konstant,

Form X=Y und Y ist begrenzt.
Datalog kann wesentlich effizienter verarbeitet werden als Prolog
Literatur: J. D. Ullman: Principles of Database and Knowledge-Base Systems.
Bd. I, Kap. 3. Computer Science Press 1988
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
32
Beispiele unbegrenzter Variabler
größer als(X,Y) :- X>Y.
vater(A,B) :- mann(A) .
X,Y unbegrenzt, da ,,X>Y`` eingebaut, nicht benutzerdefiniert.
A begrenzt, B unbegrenzt.
Intuitive Idee: Aussagen können nur aus Fakten abgeleitet werden und
sich nur auf Terme (Variable/Konstante) beziehen,
die dort vorkommen; daher Beschränkung auf sichere Fakten.
 Fakten ohne Funktionssymbole: relationale Algebra
 Zusätzliche Implikationsklauseln: deduktive Datenbanken
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
33
Wiederholung relationale Algebra
gegeben: Relationen
R(A,B,C) = { (a,b,c), (d,a,f), (c,b,d) }
S(A,B,D) = { (d,a,g), (d,a,c), (c,b,g) }
 Projektion:
π A,B (R) = { (a,b), (d,a), (c,b) }


Selektion:
σ B=b (R) = { (a,b,c), (c,b,d) }
natürlicher Verbund (join):
 (R , S) = R  S = { (d,a,f,g), (d,a,f,c), (c,b,d,g) }
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
34
Reduktion Datalog → relationale Algebra
Nichtrekursive Klauseln
nicht-rekursiv: Implikation q(...) :- q1(...),...,qm(...) hängt weder direkt noch
indirekt von q(...) ab

Implikationen qj(...) :- ..., qi(...), ... können so angeordnet werden, daß i < j

Konjunktion des Rumpfs ..., qi(...), ... bildet eine Relation r(...),
nämlich den natürlichen Verbund q1(...)  ...  qm(...) des Rumpfs

Argumente: die im Rumpf vorkommenden Variablen
Wegen Anordnung ist r ohne Rückgriff auf Kopf qj(...) berechenbar

Wegen Begrenztheit kommen alle Variablen X in qj(...,X,...) auch in r vor

also: Kopf qj(...) ist Relation seiner Variablen und ergibt sich durch Projektion

des Rumpfs r auf diese Variablen
bei mehreren Rümpfen zum gleichen Kopf:
Vereinigung, d.h. Disjunktion der Rümpfe bilden


Einsicht: nicht-rekursive Implikation ist zusammengesetzte
Operation der Relationenalgebra
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
35
Elimination
Umbenennen von Variablen
zusätzliche Literale
 X=Y für gleiche Variablen oder
 X=c für Konstanten.
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
36
2 Relation der Rümpfe

gegeben: Klauseln q1, ... , qm

natürlichen Verbund der qi

Selektion besonderer Prädikate

Vergleichsoperationen für Selektion definiert
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
37
3 Relation der Köpfe


Projektion entsprechend der Variablen im Kopf
Vereinigung der Relationen der RümpfeBerechne die Relation für jeden Kopf
wie bei nichtrekursiven Klauseln
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
38
Beispiel
geschwister(X,Y):eltern(X,Z)& eltern(Y,Z)& X/=Y.
vetter(X,Y):eltern(X,Z)& eltern(Y,Z')&
geschwister(Z,Z').
G(X,Y) := πX,Y(σ X¹Y(E(X,Z)  E(Y,Z)))
V(X,Y) := πX,Y(E(X,Z)  E(Y,Z)  G(Z,Z))
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
39
Rekursive Klauseln
Ersetze :- durch =, d.h. jede Implikation setzt sich selbst voraus
 bedenke:

rekursive Implikation q(...) :- q1(...),...,qm(...) nur sinnvoll,
wenn es wenigstens eine nicht-rekursive Implikation für das gleiche q(...) gibt

daher erfüllt die Lösung des nicht-rekursiven Falls die Gleichung

alle weitere Lösungen sind umfangreicher: Halbordnung durch Mengeninklusion
 Gesamtlösung ist minimaler Fixpunkt des Gleichungssystems
 Gesamtlösung durch Iteration berechenbar
(gleiche Methodik wie bei iterativer Lösung von Datenflußgleichungen)
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
40
Beispiel (fortgesetzt)
...
vetter(X,Y):eltern(X,Z)& eltern(Y,Z')& geschwister(Z,Z').
vetter(X,Y):eltern(X,Z)& eltern(Y,Z')& vettern(Z,Z').
V (X,Y) = πX,Y (E (X,Z)  E (Y,Z)  G (Z,Z)) ∪
πX,Y (E (X,Z)  E (Y,Z)  V (Z,Z))
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
41
Auswertungsalgorithmus
Initialisiere

linke Seiten

extensional gegebene Relationen (Fakten) und

intensional gegebene Relationen (Implikationen) mit Ø.
 Berechne rechte Seiten
 Wiederhole bis Fixpunkt intensionaler Relationen erreicht
Wohldefiniert weil:
 Regeln sicher
 Operationen (  , ∪ , ... ) monoton bzgl. ⊆

Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
42
Negation
Negation, d.h. Übergang zum Mengenkomplement der Relationen
in Datalog nicht erlaubt, da dann minimaler Fixpunkt nicht
eindeutig:
(1) r(1).
(2) p(X) :- r(X) & q(X)
(3) q(X) :- r(X) & p(X)
P=R-Q Q=R-P
(S1)
(S2)
P = ØQ = {1}
P = {1}
Q= Ø
Minimaler Fixpunkt nicht eindeutig trotz geschlossener Welt.
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
43
Einschränkung des Verbots der
Negation



Geschichtete (stratified) Negationen in sicheren Regeln
Kopf P und negiertes Literal ¬S im Rumpf,
dann keine transitive Abhängigkeit von P und positivem Literal S.
Minimaler Fixpunkt dann eindeutig.
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
44
Herunterladen