Interpreter (Hilfsfunktionen)

Werbung
Funktionale Programmierung
Interpreter (Hilfsfunktionen)
-- Berechnet die Liste der gebundenen Variablen
boundList :: Expr -> [String]
boundList (Var x)
= []
boundList (Lambda x e)
= x : (boundList e)
boundList (App e1 e2)
= (boundList e1) ++ (boundList e2)
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Interpreter (Hilfsfunktionen)
-- Berechnet die Menge FV (Freie Variablen)
freeList :: Expr -> [String] -> [String]
freeList (Var x)
bound
| elem x bound
= []
| otherwise
= [x]
freeList (Lambda x y) bound = freeList y ( x : bound )
freeList (App x y) bound
= (freeList x bound)
++(freeList y bound)
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Definition der Ersetzungsfunktion
Für beliebige Ausdrücke E1, E2 und eine Variable x, definieren wir E2[E1\x]
als die Ersetzung aller freien Vorkommen der Variable x durch E1 in E2 mit
eventuellen Umbenennungen von gebundenen Variablennamen, um
Namens-Konflikte zu vermeiden.
a)
x[E1\x]
≡ E1
b) y[E1\x]
≡ y
für alle Variablen y ≠ x
c) (E2E3)[E1\x]
≡ E2 [E1\x] und E3 [E1\x]
d) (λx.E2)[E1\x]
≡ λx.E2
e) (λy.E2)[E1\x]
≡ λy.E2
wenn x∉FV(E2)
f) (λy.E2)[E1\x]
≡ λy.(E2 [E1\x])
wenn x∈FV(E2) und y∉FV(E1)
g) (λy.E2)[E1\x]
≡ λz.(E2[E1\x][z\y]) wenn x∈FV(E2) und y∈FV(E1)
In e), f) und g) ist y ≠ x. In g) wird die erste Variable gewählt, die ∉FV(E1E2)
ist.
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Reduktionsstrategien in λ-Ausdrücken
((λ x.x) (λ y.yz)) ((λ a.a) (λ b.bw))
(λ y.yz) ((λ a.a) (λ b.bw))
((λ a.a) (λ b.bw)) z
(λ b.bw)z
zw
Prof. Dr. Margarita Esponda
(λ y.yz) (λ b.bw)
(λ b.bw)z
zw
((λ x.x) (λ y.yz)) (λ b.bw)
(λ y.yz) (λ b.bw)
(λ b.bw)z
zw
Funktionale Programmierung
Reduktionsstrategien in λ-Ausdrücken
Die Call-by-Name Auswertungsstrategie reduziert immer den am
weitesten oben und am weitesten links stehenden Redex und
sonst nichts.
(λ x. E1 ) E2 ⇒β E1 [ E2 \ x ]
Die Call-by-Value Auswertungsstrategie reduziert die Lambda Ausdrücke nur, wenn die Argumente wiederum λ-Ausdrücke oder
Variablen sind.
(λ x. E1 ) v ⇒β E1 [ v \ x ]
mit v = λ-Abstraktion oder Variable
Die Auswertung geht von innen nach außen und von links nach
rechts.
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Call-by-Name Reduktionsstrategie
oder
Normalordnung-Reduktion
((λ x.x) (λ y.yz)) ((λ a.a) (λ b.bw))
(λ y.yz) ((λ a.a) (λ b.bw))
((λ a.a) (λ b.bw)) z
(λ b.bw)z
zw
Prof. Dr. Margarita Esponda
(λ y.yz) (λ b.bw)
(λ b.bw)z
zw
((λ x.x) (λ y.yz)) (λ b.bw)
(λ y.yz) (λ b.bw)
(λ b.bw)z
zw
Funktionale Programmierung
Call-by-Name
Probleme:
(λ x. λ y.yxxz)(λ a.ya) ⇒ λ y.y(λ a.ya)(λ a.ya)z
Teilausdrücke werden nicht mehr reduziert
(λ y. λ z. z)((λ x.xx)(λ x.xx)) ⇒ λ z. z
Call-by-Value
Probleme:
Prof. Dr. Margarita Esponda
(λ y. λ z. z)((λ x.xx)(λ x.xx)) ⇒
Endlosschleifen!
Funktionale Programmierung
Interpreter (1. Version)
eval :: Expr->Expr
eval (Var x)
= Var x
eval (Lambda x exp)
= (Lambda x exp)
eval (App (Var x) exp)
= (App (Var x) (eval exp))
eval (App (Lambda a e2) e1)
= eval (subst a e1 e2)
eval (App (App e2 e1) e3)
| (evale21 == (App e2 e1)) = (App (App e2 e1) e3)
| otherwise
= eval (App evale21 e3)
where evale21 = eval (App e2 e1)
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Interpreter (Ersetzungsfunktion)
-- ersetzt alle Vorkommen von x in dem Lambda-Ausdruck des
-- dritten Arguments mit dem Ausdruck exp.
subst :: String -> Expr -> Expr -> Expr
subst x exp (Var y)
| x==y
= exp
| otherwise
= Var y
subst x exp (Lambda y z)
| x==y
= Lambda y z
| (elem y (freeList exp [])) = subst x exp (rename y new (Lambda y z))
| otherwise
= (Lambda y (subst x exp z))
where new = find_new_name ( (freeList exp [])
++ (freeList z [])
++ (boundList z) )
subst x exp (App y z) = App (subst x exp y) (subst x exp z)
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Interpreter (Hilfsfunktionen)
-- Benennt die Variable y in den neuen Namen n um
rename :: String -> String -> Expr -> Expr
rename y n (Var x)
| x==y
= Var n
| otherwise
= Var x
rename y n (Lambda x e)
| x==y
= (Lambda n (rename y n e))
| otherwise
= (Lambda x (rename y n e))
rename y n (App e1 e2)
= (App (rename y n e1)
(rename y n e2))
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Interpreter (Hilfsfunktionen)
-- Ein neuer Variablenname wird gesucht.
find_new_name :: [String] -> String
find_new_name prohibited =
head [ [u]|u<-['a'..'z'],
not(elem [u] prohibited ) ]
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Anonyme Funktionen
Anonym-Funktionen können in Haskell mit Hilfe von λ-Ausdrücken
programmiert werden.
Beispiele:
fx
= exp
g x y = exp
-------
f = \x → exp
g = \x y → exp
fact
f
= \n -> foldl (\x y -> x*y) 1 [1..n]
= zipWith (\x y → x*x + y*y)
h ls
= map (\xs -> zip xs [1..]) ls
h ["abc", "abc"] ⇒ [[('a',1),('b',2),('c',3)],[('a',1),('b',2),('c',3)]]
für das schnelle Implementieren einfacher Hilfsfunktionen
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Anonyme Funktionen
Beispiel:
Wir können unseren Y-Operator in Haskell wie folgt definieren:
fix rec = rec (fix rec)
factorial = \r n -> if n==0 then 1 else ((*) n (r (n-1)))
fibs
= \r n -> if n<=1 then n else ((+) (r (n-1)) (r (n-2)))
(fix factorial) 9 ⇒ 362880
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Literatur
A Tutorial Introduction to the Lambda Calculus.
Raúl Rojas.
http://www.inf.fu-berlin.de/lehre/WS03/alpi/lambda.pdf
A Brief and Informal Introduction to the Lambda Calculus.
Paul Hudak. Spring 2008.
http://plucky.cs.yale.edu/cs201/lambda.pdf
Prof. Dr. Margarita Esponda
Herunterladen