Deklarative Programmierung

Werbung
Was bisher geschah
I
Deklarative vs. imperative Programmierung
I
Deklarative Programmierung
Funktionale Programmierung in Haskell:
I
Algebraische Datentypen
I
Pattern Matching
I
(eingeschränkte) Polymorphie, Typklassen
I
Rekursive Datentypen:
Peano-Zahlen, Listen, binäre Bäume
I
Rekursive Funktionen
I
strukturelle Induktion
Funktionen als Daten
bisher:
f :: Int -> Int
f x = 2 * x + 5
äquivalent: Lambda-Ausdruck
f = \ x -> 2 * x + 5
Lambda-Kalkül: Alonzo Church 1936, Henk Barendregt 1984,
...
Funktionsanwendung:
( \ x -> B ) A
=
B [ x := A ]
ist nur erlaubt, falls keine in A freie Variable durch ein λ in B
gebunden wird.
Der Lambda-Kalkül
. . . als weiteres Berechnungsmodell,
(vgl. Termersetzungssysteme, Turingmaschine,
Random-Access-Maschine)
Syntax (induktive Definition):
Die Menge der Lambda-Terme Λ( ) mit Variablen aus
X
X ist
IA: jede Variable ist ein Term: v ∈ X ⇒ v ∈ Λ(X)
IS: Applikation , Funktionsanwendung:
Für alle F ∈ Λ( ), A ∈ Λ( ) gilt (FA) ∈ Λ( )
Abstraktion , Funktionsdefinition:
Für alle v ∈ , B ∈ Λ( ) gilt (λv .B) ∈ Λ( )
X
X
X
X
X
Semantik: eine Relation →β auf Λ( )
(vgl. →R für Termersetzungssystem R)
X
X
Freie und gebundene Variablen(vorkommen)
X
X
I
Das Vorkommen von v ∈ an Position p in Term t ∈ Λ( )
heißt frei, wenn „darüber kein λv . . . . steht“
I
Definition (durch strukturelle Induktion):
fvar(t) = Menge der in t frei vorkommenden Variablen
I
Eine Variable x heißt in A gebunden, falls A einen
Teilausdruck λx.B enthält.
I
bvar(t) = Menge der in t gebundenen Variablen
Beispiele:
I
fvar(x(λx.λy .x)) = {x},
I
bvar(x(λx.λy .x)) = {x, y }
Semantik des Lambda-Kalküls
X
Relation →β auf Λ( ) (ein Reduktionsschritt)
Es gilt t →β t 0 , falls
I
I
I
∃p ∈ Pos(t), so daß
t[p] = (λx.B)A mit bvar(B) ∩ fvar(A) = ∅
t 0 = t[p := B[x := A]]
dabei bezeichnet B[x := A] ein Kopie von B, bei der jedes
freie Vorkommen von x durch A ersetzt ist
Ein (Teil-)Ausdruck der Form (λx.B)A heißt Redex.
(Dort kann weitergerechnet werden.)
Ein Term ohne Redex heißt Normalform.
(Normalformen sind Resultate von Rechnungen.)
Relation →α : gebundene Umbenennung
Lambda-Terme: verkürzte Notation
I
Applikation als links-assoziativ auffassen, Klammern
weglassen:
(. . . ((FA1 )A2 ) . . . An ) ∼ FA1 A2 . . . An
Beispiel: ((xz)(yz)) ∼ xz(yz)
I
geschachtelte Abstraktionen unter ein Lambda schreiben:
λx1 .(λx2 . . . . (λxn .B) . . . ) ∼ λx1 x2 . . . xn .B
Beispiel: λx.λy .λz.B ∼ λxyz.B
Funktionen höherer Ordnung
Funktionen als Argument von Funktionen
Beispiel:
twice :: (a -> a) -> a -> a
twice f x = f (f x)
Anwendung:
I
double hat den Typ Int -> Int
I
twice double hat den Typ Int -> Int
I
twice double 3
hat den Typ Int und den Wert ?
I
\x -> 2 * x + 1 hat den Typ Int -> Int
twice (\x -> 2 * x + 1)
hat den Typ Int -> Int
I
I
twice (\x -> 2 * x + 1) 3
hat den Typ Int und den Wert ?
I
succ 0, twice succ 0, twice twice succ 0
I
twice (^2) 3, twice twice (^2) 3
I
Typ von twice twice ? Typ von twice twice twice ?
Funktionen höherer Ordnung – Beispiele
I
punktweise Summe zweier Funktionen:
fsum :: (a -> Int) -> (a -> Int) -> (a -> Int)
fsum f g x = (f x) + (g x)
fsum f g = \x -> (f x) + (g x)
Beispiele:
I
I
I
fsum (*2) (+1) 4,
fsum len head [ 2 .. 5 ]
Komposition von Funktionen:
(.) :: (a -> b) -> (b -> c) -> (a -> c)
(f . g) x = f (g x)
(f . g) = \ x -> f (g x)
Beispiele:
I
I
( ( \ x -> x * 2 ) . len ) "foo"
suchbaum = sortiert . inorder
Herunterladen