Funktionale vs. logische Programmierung: Funktionale vs. logische Programmierung: Vergleich theoretische Basis der Berechnungen • funktionale Programme unterscheiden zwischen Eingaben (Argumente von Funktionen) und Ausgaben (Werte von Funktionen) • funktionale Programme: Substitution • relationale Programme in Prolog: Unifikation und Resolution • relationale Programme treffen diese Unterscheidung nicht notwendigerweise • was Eingabe und was Ausgabe einer Berechnung mit einem relationalen Programm sein soll, wird durch die Art der Invokation festgelegt (m.a.W. höhere Flexibilität) WS 2006/2007, Programmierkonzepte und Modellierung (PKM), © Prof. Dr. D. Rösner; erstellt: 4. Dezember 2006 225 Funktionale vs. logische Programmierung: 226 Fallbeispiel: Umdrehen einer Liste cont. Fallbeispiel: Umdrehen einer Liste • Haskell: mit Pattern matching • Prolog: rev :: [a] -> [a] rev [] = [] rev (x:xs) = rev xs ++ [x] rev([],[]). rev([X|Y],Z) :- rev(Y,Z1), append(Z1,[X],Z). • Haskell: Variante mit Fallunterscheidung • Scheme: rev :: Eq a => [a] -> [a] (define (rev l) (if (null? l) l (append (rev (cdr l)) (list (car l))))) WS 2006/2007, Programmierkonzepte und Modellierung (PKM), © Prof. Dr. D. Rösner; erstellt: 4. Dezember 2006 WS 2006/2007, Programmierkonzepte und Modellierung (PKM), © Prof. Dr. D. Rösner; erstellt: 4. Dezember 2006 rev x = if x == [] then [] else rev (tail x) ++ [head x] 227 WS 2006/2007, Programmierkonzepte und Modellierung (PKM), © Prof. Dr. D. Rösner; erstellt: 4. Dezember 2006 228 Funktionale vs. logische Programmierung: Fallbeispiel: Mergesort cont. Fallbeispiel: Mergesort (cf. [Mueller & Page, Ch. 34]) • merge is predefined, redefined as mymerge • Prolog: mymerge([], X, X). mymerge(X, [], X). mergesort([], []) :- !. mergesort([X], [X]) :- !. mymerge([X1|R1], [X2|R2], [X1|R]) :- precedes(X1, X2), mymerge(R1, [X2|R2], R). mergesort(X, Sorted) :- split(X, X1, X2), mergesort(X1, S1), mergesort(X2, S2), merge(S1, S2, Sorted). mymerge([X1|R1], [X2|R2], [X2|R]) :- precedes(X2, X1), mymerge([X1|R1],R2, R). • Prolog benötigt Hilfsvariable (hier: S1, S2), um Zwischenergebnisse zu ‘transportieren’ WS 2006/2007, Programmierkonzepte und Modellierung (PKM), © Prof. Dr. D. Rösner; erstellt: 4. Dezember 2006 229 Fallbeispiel: Mergesort cont. WS 2006/2007, Programmierkonzepte und Modellierung (PKM), © Prof. Dr. D. Rösner; erstellt: 4. Dezember 2006 230 Fallbeispiel: Mergesort (cf. [Mueller & Page, Ch. 34]) • Haskell: • weitere Hilfsprädikate: /* split a list of n elements into two near halfes */ sort :: Ord a => [a] -> [a] /* firstn(X, 0, [], X). */ firstn([X|Y], 1, [X], Y). firstn([X|Y], N, [X|YN], RN) :- N1 is N-1, firstn(Y, N1, YN, RN). sort [] = [] sort [x] = [x] sort seq = merge (sort a) (sort b) where (a,b) = split seq • flexible Kombination von Funktionsaufrufen split(X, X1, X2) :- length(X,N), N2 is ceiling(N/2), firstn(X, N2, X1, X2). • in Verbindung mit Pattern zum Zugriff auf Elemente eines Paares WS 2006/2007, Programmierkonzepte und Modellierung (PKM), © Prof. Dr. D. Rösner; erstellt: 4. Dezember 2006 231 WS 2006/2007, Programmierkonzepte und Modellierung (PKM), © Prof. Dr. D. Rösner; erstellt: 4. Dezember 2006 232 Fallbeispiel: Mergesort (cf. [Mueller & Page, Ch. 34]) Wichtiger Unterschied • Hilfsfunktionen: • Pattern matching in Prolog: split :: [a] -> ([a],[a]) split [] = ([],[]) split seq = splitAt (div (length seq) 2) seq all_equal([]). merge :: Ord a => [a] -> [a] -> [a] merge xs [] = xs merge [] ys = ys merge (x:xs) (y:ys) | x == y = x:(merge xs ys) | x < y = x:(merge xs (y:ys)) | otherwise = y:(merge (x:xs) ys) all_equal([X,X | Y]) :- all_equal([X | Y]). WS 2006/2007, Programmierkonzepte und Modellierung (PKM), © Prof. Dr. D. Rösner; erstellt: 4. Dezember 2006 all_equal([_]). 233 Wichtiger Unterschied cont. 234 Relationale Programme als ‘Generatoren’ • all_equal als Prädikat • Pattern matching in Haskell: ?- all_equal([a,a,a,a]). Yes allEqual :: Eq a => [a] -> Bool allEqual [] = True allEqual [_] = True allEqual (el1:el2:rest) = if el1 == el2 then allEqual (el2:rest) else False • all_equal als ‘Generator’ • Haskell: eine Variable darf in einem Pattern auf der linken Seite einer Definition nur einmal auftauchen WS 2006/2007, Programmierkonzepte und Modellierung (PKM), © Prof. Dr. D. Rösner; erstellt: 4. Dezember 2006 WS 2006/2007, Programmierkonzepte und Modellierung (PKM), © Prof. Dr. D. Rösner; erstellt: 4. Dezember 2006 235 ?- all_equal(X). X = [] ; X = [_G205] ; X = [_G205, _G205] ; X = [_G205, _G205, _G205] ; ... WS 2006/2007, Programmierkonzepte und Modellierung (PKM), © Prof. Dr. D. Rösner; erstellt: 4. Dezember 2006 236