Programmieren in Haskell

Werbung
Universität Bielefeld
Programmieren
in Haskell
Sauthoff
Programmieren in Haskell
Rechenstrategien
Strategien
WS 2011/2012
Georg Sauthoff1
Universität Bielefeld
AG Praktische Informatik
November 15, 2011
1
[email protected]
Wiederholung length
Universität Bielefeld
Programmieren
in Haskell
Sauthoff
1
2
3
Die Funktion length hatten wir wie folgt definiert:
length
:: [ a ] -> Int
length
[] = 0
length ( x : xs ) = 1 + length xs
Aber was ist von folgender Definition zu halten?
4
length xs ++ ys == length xs + length ys
reicht das?
Rechenstrategien
Wiederholung length
Strategien
Grundbegriffe zu Auswertungs-Strategien:
Universität Bielefeld
Programmieren
in Haskell
Sauthoff
Rechnen
=
Anwenden von Gleichungen in Formeln
Redex
=
Stelle in einer Formel, an der die linke Seite
einer Gleichung “passt” (Reducible Expression)
“passt”
=
die auf der linken Seite verlangten Konstruktoren der Argumente liegen vor
Rechenstrategien
Strategien
Normalform
Ein Ausdruck ist in Normalform wenn er keinen Redex enthält.
Beispiel
1
head ( x : xs ) = x
Universität Bielefeld
Programmieren
in Haskell
Sauthoff
2
3
4
5
6
-- ist anwendbar auf die Formel und ergibt
head (1:2:2:[])
=>
1
head (1:([3 ,4]++[5 ,6]))
=>
1
head (1: ones ) where
ones = 1: ones
=>
1
ist (noch) nicht anwendbar auf
7
8
9
10
head ([1 ,3 ,4] ++ [5 ,6])
head ( map (1+) [1 ,2 ,3])
head ones where
ones = 1: ones
Es muss erst eine Gleichung für ++, map oder ones angewandt
werden.
Rechenstrategien
Strategien
Lage von Redexen in einer Formel
Universität Bielefeld
Programmieren
in Haskell
Sauthoff
Rechenstrategien
Strategien
Ein Redex ist
innermost, wenn er keinen weiteren Redex enthält,
outermost, wenn er in keinem weiteren Redex enthalten ist,
“zwischendrin”, sonst.
Beispiel
Universität Bielefeld
Programmieren
in Haskell
Sauthoff
Rechenstrategien
Strategien
Auswertungs-Strategien
Universität Bielefeld
Programmieren
in Haskell
Sauthoff
Rechenstrategien
leftmost innermost: immer den Redex wählen, der am
weitesten links steht und innermost ist.
leftmost outermost: immer den Redex wählen, der am
weitesten links steht und outermost ist.
gemischt: man kann sich viele weitere Strategien
vorstellen . . .
Strategien
if-then-else
Universität Bielefeld
Besonderheit von if_then_else:
Programmieren
in Haskell
Sauthoff
Seine definierenden Gleichungen sind
Rechenstrategien
Strategien
if True then x else y = x
(1)
if False then x else y = y
(2)
Ein Redex
wird in jedem Fall leftmost outermost berechnet.
Je nach Ergebnis für C wird A oder B nicht berechnet.
Universität Bielefeld
Programmieren
in Haskell
Sauthoff
Rechenstrategien
Diese Regel für if_then_else gilt in allen
Programmiersprachen.
Ohne sie könnte man keine terminierende Rekursion
programmieren:
f ( x ) = if x <= 0 then else 2 + f (x -1)
Innermost-Strategie führt zu endloser Berechnung des
else-Falles.
Strategien
Eigenschaften der Strategien
Universität Bielefeld
Programmieren
in Haskell
1
Ob eine Rechnung terminiert, hängt i.A. von der Strategie
ab.
2
Wenn zwei verschiedene Strategien, angewandt auf die
gleiche Formel, terminieren, liefern sie das gleiche
Ergebnis.
3
Im Fall (2) kann sich der Rechenaufwand stark
unterscheiden.
4
Wenn für eine Formel F irgendeine Strategie terminiert,
dann terminiert für F auch “leftmost outermost”.
5
“leftmost innermost” terminiert seltener als “leftmost
outermost”.
Sauthoff
Rechenstrategien
Strategien
Anschauliche Bedeutung
Universität Bielefeld
Programmieren
in Haskell
Sauthoff
Rechenstrategien
innermost: Alle Argumente einer Funktion werden ganz
ausgerechnet, bevor die Funktion “aufgerufen”
wird.
outermost: Die Argumente einer Funktion werden immer nur
so weit ausgerechnet, wie es die Funktion für
ihren nächsten Schritt braucht.
Strategien
Lazy Evaluation
Universität Bielefeld
Programmieren
in Haskell
Sauthoff
Rechenstrategien
Strategien
Haskell verwendet lazy evaluation (verzögerte Auswertung), das
ist leftmost outermost + graph reduction
graph reduction ist eine Zusatzregel, die die Duplikation
unausgerechneter Formeln vermeidet.
Beispiel zur graph reduction
Universität Bielefeld
Programmieren
in Haskell
Sauthoff
1
twice x = x * x
twice
(3 + 4)
↑
↑
outermost innermost
würde blindlings outermost reduziert zu
(3 + 4) ∗ (3 + 4)
wo nun der Ausdruck (3 + 4) zweimal berechnet werden müsste.
Rechenstrategien
Strategien
Universität Bielefeld
Programmieren
in Haskell
Sauthoff
Rechenstrategien
Strategien
1
2
Stattdessen wird reduziert
twice (3+4) = x * x
where x = 3+4
worin durch die “Nebenrechnung” 3 + 4 nur einmal berechnet
wird.
Einfluss von Lazy Evaluation auf die Auswertung
Universität Bielefeld
Programmieren
in Haskell
Sauthoff
Rechenstrategien
Strategien
Unter lazy evaluation kann es sein, dass eine Funktion in einem
bestimmten Kontext nur einen Teil ihres Ergebnisses berechnet.
Universität Bielefeld
Programmieren
in Haskell
Sauthoff
Rechenstrategien
Hier die naheliegende Implementierung von minimum:
1
2
3
4
minimum ( a : as ) = min a as where
min a []
= a
min a ( b : x ) = if a <= b then min a x
else min b x
Strategien
Universität Bielefeld
Programmieren
in Haskell
Sauthoff
Rechenstrategien
Hier eine alternative Implementierung, die bequemerweise den
Insertion-Sort benutzt
minimum ( a : as ) = head ( isort ( a : as ))
Sehen wir genauer hin!
Strategien
Universität Bielefeld
Programmieren
in Haskell
Sauthoff
Rechenstrategien
Strategien
1
2
3
4
5
Die Definition von isort war:
isort [] = []
isort ( a : as ) = insert a ( isort as )
insert a [] = [ a ]
insert a ( b : as ) = if a <= b then a : b : as
else b :( insert a as )
Universität Bielefeld
Lazy Evaluation berechnet in einer Formel immer an der
“äußersten” Stelle, an der eine Gleichung anwendbar ist:
Programmieren
in Haskell
Zunächst kann immer nur die Gleichung isort.2 angewandt
werden, am Ende einmal isort.1
Rechenstrategien
head
head
isort
insert
:
=>
a1
Sauthoff
insert
:
a1
a2
a2
insert
:
an
an
[]
[]
Strategien
Universität Bielefeld
Danach wird n-mal insert angewandt, beginnend bei an .
Nehmen wir an, a5 ist das kleinste Element. Streng
“outermost” entsteht nun
Programmieren
in Haskell
Sauthoff
Rechenstrategien
head
Strategien
:
=>
a5
insert
a1
insert
a2
insert
a n−1
innerhalb des Kastens
könnte man weiterrechnen, aber das wäre nicht
“outermost”.
[a n]
Universität Bielefeld
Programmieren
in Haskell
head braucht nicht mehr als den obersten Konstruktur (:), um
sein Ergebnis zu liefern
Sauthoff
Rechenstrategien
Strategien
head
=>
a5
:
a5
Es werden ∼ 2 · n Gleichungen angewandt. Der Rest der
Operationen steckt im Kasten und wird nicht benötigt!
Fazit
Universität Bielefeld
Programmieren
in Haskell
Sauthoff
Rechenstrategien
Strategien
Durch Lazy Evaluation müssen weniger Reduktionen
durchgeführt werden.
Herunterladen