6. Funktionen als Daten, Übersicht Notation von Lambda

Werbung
FP-6.1
FP-6.2
6. Funktionen als Daten, Übersicht
Notation von Lambda-Ausdrücken
Orthogonales Typsystem: Funktionen sind beliebig mit anderen Typen kombinierbar
Auswertung eines Lambda-Ausdruckes
liefert eine Funktion, als Datum, unbenannt.
Notation für Funktionswerte (Lambda-Ausdruck):
fn (z,k) => z*k
Notation:
Datenstrukturen mit Funktionen als Komponenten:
z. B. Suchbaum für Funktionen
fn ParameterMuster => Ausdruck
Funktionale, Funktionen höherer Ordnung (higher order functions, HOF):
haben Funktionen als Parameter oder als Ergebnis
fn (z,k) => z*k
fn (x, y) => Math.sqrt (x*x + y*y)
mit Fallunterscheidung:
Berechnungsschemata:
Funktion als Parameter abstrahiert Operation im Schema,
wird bei Aufruf des Schemas konkretisiert
(hier noch ohne Currying)
schrittweise Parametrisierung (Currying):
Funktion als Ergebnis bindet ersten Parameter,
nützliche Programmiertechnik, steigert Wiederverwendbarkeit
val chorner = fn l => fn x => foldl (fn (z,k) => z*x+k, l, 0);
nicht-endliche Datenstrukturen (Ströme, lazy evaluation), (Kapitel 7):
Funktionen als Komponenten von Datenstrukturen,
z. B. Funktion, die den Rest einer Liste liefert
datatype 'a seq = Nil | Cons of 'a * (unit -> 'a seq)
Muster1 => Ausdruck1
Muster2 => Ausdruck2
...
Mustern => Ausdruckn
fn nil => true
| (_::_) => false
© 2004 bei Prof. Dr. Uwe Kastens
© 2012 bei Prof. Dr. Uwe Kastens
foldl (fn (z,k) => z*k, [2,5,1], 1);
fn
|
|
|
Anwendungen von Lambda-Ausdrücken:
linsert (l, fn (z,k) => z*x+k, 0)
(fn (z,k) => z*k) (a, b)
if b then fn (z,k) => z*k
else fn (z,k) => z+k
[fn (z,k) => z*k, fn (z,k) => z+k]
val null =
fn nil => true
| (_::_) => false;
fun Comp (f, g) = fn x => f (g x);
FP-6.3
FP-6.4
Currying
Funktionen in Datenstrukturen
Haskell B. Curry: US-amerikanischer Logiker 1900-1982, Combinatory Logic (1958);
M. Schönfinkel hatte die Idee schon 1924:
Statt Parametertupel schrittweise parametrisieren:
fun prefix (pre, post) = pre ^ post;
Signatur: string * string -> string
curried:
fun prefix pre = fn post => pre ^ post;
Signatur: string -> (string -> string)
gleich:
string -> string -> string
Erster Parameter (pre) ist in der Ergebnisfunktion gebunden.
Kurznotation:
fun prefix pre post = pre ^ post;
Liste von Funktionen:
val titlefns =
[prefix "Sir ",
prefix "The Duke of ",
prefix "Lord "]
hd (tl titlefns) "Gloucester";
Curry-Form von Funktionen
ist allgemeiner verwendbar
als Tupelform!
Suchbaum mit (string * (real -> real)) Paaren:
val fntree =
Dict.insert
(Dict.insert
(Dict.insert
(Lf, "sin", Math.sin),
"cos", Math.cos),
"atan", Math.atan);
fun repnlist n x = if n=0 then [] else x :: repnlist (n-1) x;
© 2004 bei Prof. Dr. Uwe Kastens
© 2004 bei Prof. Dr. Uwe Kastens
Anwendungen:
val knightify = prefix "Sir "; val dukify = prefix "The Duke of ";
knightify "Ratcliff";
(prefix "Sir ") "Ratcliff";
prefix "Sir " "Ratcliff";
linksassoziativ
auch rekursiv:
x oder n ist in der Ergebnisfunktion gebunden
fun repxlist x n = if n=0 then [] else x :: repxlist x (n-1);
:(string -> string) list
Dict.lookup (fntree, "cos") 0.0;
FP-6.5
FP-6.6
Currying als Funktional
Komposition von Funktionen
Funktional: Funktionen über Funktionen; Funktionen höherer Ordnung (HOF)
Ausdrücke mit Operatoren, die Funktionen zu neuen Funktionen verknüpfen
infix o;
fun (f o g) x = f (g x);
('b->'c) * ('a->'b) -> 'a->'c
secl, secr (section):
2-stellige Funktion in Curry-Form wandeln; dabei den linken, rechten Operanden binden:
fun secl x f y = f (x, y);
'a -> ('a * 'b -> 'c) -> 'b -> 'c
fn x => 2.0 / (x - 1.0)entspricht
(secl 2.0 op/) o (secr op- 1.0)
Potenzieren von Funktionen fn(x) :
fun repeat f n x =
if n > 0 then repeat f (n-1) (f x)
else x;
('a->'a) -> int -> 'a -> 'a
(repeat secr op/ 2.0 3) (800.0)
fun secr f y x = f (x, y);
('a * 'b -> 'c) -> 'b -> 'a -> 'c
val twoPow = secl 2.0 power;
int -> real
val pow3 = secr power 3;
real -> real
klassische Kombinatoren S K I:
© 2004 bei Prof. Dr. Uwe Kastens
© 2004 bei Prof. Dr. Uwe Kastens
Anwendungen:
fun power (x, k):real =if k = 1 then x else
if k mod 2 = 0then
power (x*x, k div 2)
else x *power (x*x, k div 2);
map (l, secr power 3);
val knightify = (secl "Sir " op^);
string -> string
op^ bedeutet infix-Operator ^ als Funktion
FP-6.7
Reihenberechnung als Schema
Allgemeine Formel für eine endliche Reihe:
Σ i=0
m-1
f(i)
fun summation f m =
let fun sum (i, z):real =
akkumulierende Hilfsfunktion
if i=m then z else sum (i+1, z + (f i))
in sum (0, 0.0) end;
Signatur: (int->real) -> int -> real
Aufruf summation (fn k => real(k*k)) 5;
liefert 30
Doppelsumme:
Σ i=0 Σ j=0
m-1
n-1
g(i,j)
summation als Parameter von summation:
© 2008 bei Prof. Dr. Uwe Kastens
Bindung
summation(fn i => summation (fn j => g(i,j)) n) m
int->real
int->real
einfacher h i j statt g(i,j): summation (fn i => summation (h i) n) m;
Kombination von Funktionen, Konversion nach real: summation (Math.sqrt o real);
Summe konstanter Werte; Kombinator K für konstante Funktion: summation (K 7.0) 10;
fun I x = x;
'a -> 'a
fun K x y = x;
'a -> 'b -> 'a
fun S x y z = x z (y z);
('a -> 'b -> 'c) -> ('a -> 'b) -> 'a -> 'c
allgemeine Form der Komposition. I entspricht S K K
Herunterladen