Standardparadigmen: Deklarative Sprachen

Werbung
Teil 3
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
Standardparadigmen:
Deklarative Sprachen



·
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))
Höhere Programmiersprachen SS 2001
1
 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
Grundfunktionen
Höhere Programmiersprachen SS 2001
2
Emacs Lisp
LaTeX-Filter
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)
(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)
...
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
y
x
funktionales Programmieren: Lisp 1.5
logisches Programmieren: Prolog
relationales Programmieren: Datalog
Prof. Dr. Gerhard Goos
·
3
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
4
nil
Der Sündenfall: Zuweisungen in Lisp
Emacs Lisp
Alle heutigen Versionen von Lisp (Emacs Lisp, Scheme, Common Lisp, ...)
erlauben Zuweisungen:
Türme von Hanoi
Variablenvereinbarung (in Emacs Lisp):
(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) ... )
(defvar variable)
oder
(defvar variable anfangswert)
oder
(defvar variable anfangswert ''Dokumentation'')
(provide hanoi)
Zuweisung:
(setq variable wert)
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
5
Bedeutung:
variable zeigtHöhere
aufProgrammiersprachen
wert (keine
Kopie!)
Prof. Dr. Gerhard Goos
SS 2001
Grundprinzipien funktionaler
Sprachen










ML, Haskell und Gofer
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
6
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"
7
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
8
Konstanten als Funktionen höherer
Ordnung
Konstanten als Listen
Integer





Boolean

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
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
Konstanten als Funktionen höherer
Ordnung
Höhere Programmiersprachen SS 2001
Anwendung Funktionen höherer
Ordnung
Integer








10
Faltung
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))))]
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
add x y=reverse(addr(reverse x)(reverse y)'0')
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
11
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
12
Abstrakte Datentypen
ADT Keller
data IntKeller =
EmptyStack |
Push (Int, IntKeller)
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
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
13
Prof. Dr. Gerhard Goos
Polymorphie
Höhere Programmiersprachen SS 2001
14
Typisierung
Parametrische Polymorphie
Einsetzen eines Typs in die Typvariable ergibt neuen Typ
Muß konsistent sein
data Stack t = EmptyStack
Push (t, Stack t)
istLeer :: Stack t -> Bool
top :: Stack t -> t
pop :: Stack t -> Stack t
Typ Stack Int:
Push ( 1 Push ( 2 Push ( 3 Empty )))
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
Typ - Fehler:
Push ( 1 Push ( True Push ( 3 Empty )))
15
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
16
Dynamisch vs Statisch
Typanalyse zur Laufzeit:
 Berechnet den konkreten Typ jedes Terms
 Beispiel Lisp.
Prolog
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
Prof. Dr. Gerhard Goos
Entscheidbarkeit
Höhere Programmiersprachen SS 2001
18
Grundresolution
Klauseln K disjunktiv verknüpfte Literal
F = ∀x1, ... , xn F*
F* = K1 ∧ K2 ∧ ... ∧ Kn
Ki = P1 ∨ P2 ∨ ... ∨ Pm
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
F ist unerfüllbar gdw. K1 , K2 , ... , Kt mit



19
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
Allgemeinster Unifikator
Substitution s ist Unifikator einer Menge L von Literalen { L1, L2, ... ,Lk } wenn
L1s = L2s = ... = Lks
Grundsubstitution nicht vorausschauend
Gierig und daher ineffizient
Minimale Substitution für Resolutionsschritt
 Allgemeiner Unifikator
 Prädikatenlogische Resolution
Allgemeinster Unifikator s falls sub = s sub´
s
sub'
sub
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
21
Prof. Dr. Gerhard Goos
Unifikation
Höhere Programmiersprachen SS 2001
22
Prolog
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
Hornklauselprogramme
 Tatsachen: T(...).
 Prozedur: P(...) :- Q1 (...), Q2 (...), ... , Qn(...).
 Ziel: ?- Q1 (...), Q2 (...), ... , Qn(...).
Ergebnis eindeutig?
23
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
24
Beispiel
Mögliche SLD Resolutionen
?-Q(x,c)
(1)
(2)
?-Q(y,c),R(x,y)
(1)
(2)
(3)
Frage
(1)
Q(x,z):-Q(y,z),R(x,y).
Q(x,x).
R(b,c).
?-Q(x,c)
Q(c,c)
(2)
?-Q(y,c),R(v,x),R(x,y)
?-R(x,c)

(3)
(2)
(1)
?-R(v,x),R(x,c)
Q(b,c)
(3)
?-R(c,c)
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
25
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
Auswertestrategie
Cut
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
26
Beispiel Hilfs-not Operator
not(X) :- X, !, fail.
not(_).
27
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
28
Arithmetik Operatoren
Türme von Hanoi
:- use_module(library(lineio)).
hanoi(N):- N >=0, move(N,"A","B","C").
pow(1,_,1).
pow(_,0,1).
pow(B,E,X):-is(EE,E-1),
pow(B,EE,Y),mul(B,Y,X).
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
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).
29
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
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
30
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
Wiederholung relationale Algebra
größer als(X,Y) :- X>Y.
vater(A,B) :- mann(A) .
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) }
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
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
Reduktion Datalog → relationale Algebra
Nichtrekursive Klauseln
Höhere Programmiersprachen SS 2001
34
Elimination
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


Umbenennen von Variablen
zusätzliche Literale
 X=Y für gleiche Variablen oder
 X=c für Konstanten.
Einsicht: nicht-rekursive Implikation ist zusammengesetzte
Operation der Relationenalgebra
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
35
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
36
2 Relation der Rümpfe

gegeben: Klauseln q1, ... , qm

natürlichen Verbund der qi

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


Selektion besonderer Prädikate
Vergleichsoperationen für Selektion definiert

Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
37
Prof. Dr. Gerhard Goos
Beispiel
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)

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))
Höhere Programmiersprachen SS 2001
38
Rekursive Klauseln
geschwister(X,Y):eltern(X,Z)& eltern(Y,Z)& X/=Y.
vetter(X,Y):eltern(X,Z)& eltern(Y,Z')&
geschwister(Z,Z').
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
39
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
40
Beispiel (fortgesetzt)
Auswertungsalgorithmus
...
vetter(X,Y):eltern(X,Z)& eltern(Y,Z')& geschwister(Z,Z').
vetter(X,Y):eltern(X,Z)& eltern(Y,Z')& vettern(Z,Z').
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. ⊆


V (X,Y) = πX,Y (E (X,Z)  E (Y,Z)  G (Z,Z)) ∪
πX,Y (E (X,Z)
Prof. Dr. Gerhard Goos

E (Y,Z)  V (Z,Z))
Höhere Programmiersprachen SS 2001
41
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
42
Einschränkung des Verbots der
Negation
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= Ø

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.
Minimaler Fixpunkt nicht eindeutig trotz geschlossener Welt.
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
43
Prof. Dr. Gerhard Goos
Höhere Programmiersprachen SS 2001
44
Herunterladen