Haskell: Striktheit Haskell: Striktheit Haskell: Striktheit Haskell

Werbung
Haskell: Striktheit
Haskell: Striktheit
(vgl. [Hutton, Ch.12])
Beispiel einer nonstrikten Funktionsanwendung:
(vgl. [Hutton, Ch.12])
• Standardfall in Haskell: verzögerte Auswertung von Argumenten
sumwith :: Int -> [Int] -> Int
sumwith v [ ] = v
sumwith v (x : xs) = sumwith (v + x ) xs
• aber: strikte Auswertung von Argumenten erzwingbar
• Ausdruck der Form f $! x hat gleiche Bedeutung wie f x mit dem
einzigen Unterschied, dass oberste Ebene des Argumentausdrucks x
ausgewertet, bevor f angewendet
• Anwendung z.B. zur Optimierung bzgl. Platzbedarf
WS 2006/2007, Programmierkonzepte und Modellierung (PKM), © Prof. Dr. D. Rösner; erstellt: 15. Januar 2007
297
WS 2006/2007, Programmierkonzepte und Modellierung (PKM), © Prof. Dr. D. Rösner; erstellt: 15. Januar 2007
298
Haskell: Striktheit
Haskell: Striktheit
bei verzögerter Auswertung wird erst die komplette Summation gebildet, bevor die erste Addition erfolgt
wegen des Speicherbedarfs für die offenen Additionen stösst das Programm
sumwith schnell an Speichergrenzen:
sumwith 0 [1, 2, 3]
= { applying sumwith } sumwith (0 + 1) [2, 3]
= { applying sumwith } sumwith ((0 + 1) + 2) [3]
= { applying sumwith } sumwith (((0 + 1) + 2) + 3) [ ]
= { applying sumwith } ((0 + 1) + 2) + 3
= { applying + } (1 + 2) + 3
= { applying + } 3 + 3
= { applying + } 6
Main> sumwith 0
55
Main> sumwith 0
50005000
Main> sumwith 0
ERROR - C stack
[1,2 .. 10]
[1,2 .. 10000]
[1,2 .. 20000]
overflow
(vgl. [Hutton, Ch.12])
WS 2006/2007, Programmierkonzepte und Modellierung (PKM), © Prof. Dr. D. Rösner; erstellt: 15. Januar 2007
299
WS 2006/2007, Programmierkonzepte und Modellierung (PKM), © Prof. Dr. D. Rösner; erstellt: 15. Januar 2007
300
Haskell: Striktheit
in der folgenden strikten Variante wird mit
Akkumulator-Arguments erzwungen:
Haskell: Striktheit
$! die Auswertung des
sumwith’ :: Int -> [Int] -> Int
sumwith’ v [ ] = v
sumwith’ v (x : xs) = (sumwith’ $!(v + x )) xs
Main> sumwith’ 0 [1,2 .. 20000]
200010000
Main> sumwith’ 0 [1,2 .. 100000]
705082704
Main> sumwith’ 0 [1,2 .. 1000000]
1784293664
(vgl. [Hutton, Ch.12])
WS 2006/2007, Programmierkonzepte und Modellierung (PKM), © Prof. Dr. D. Rösner; erstellt: 15. Januar 2007
301
Haskell: Striktheit (vgl. [Hutton, Ch.12])
WS 2006/2007, Programmierkonzepte und Modellierung (PKM), © Prof. Dr. D. Rösner; erstellt: 15. Januar 2007
302
Haskell: Striktheit
strikte Variante von foldl
(vgl. [Hutton, Ch.12])
sumwith’ 0 [1, 2, 3]
= { applying sumwith’ } sumwith’ $! (0 + 1) [2, 3]
= { applying + } sumwith’ $! 1 [2, 3]
= { applying $! } sumwith’ 1 [2, 3]
= { applying sumwith’ } sumwith’ $! (1 + 2) [3]
= { applying + } sumwith’ $! 3 [3]
= { applying $! } sumwith’ 3 [3]
= { applying sumwith’ } sumwith’ $! (3 + 3) [ ]
= { applying + } sumwith’ $! 6 [ ]
= { applying $! } sumwith’ 6 []
= { applying sumwith’ } 6
WS 2006/2007, Programmierkonzepte und Modellierung (PKM), © Prof. Dr. D. Rösner; erstellt: 15. Januar 2007
Diese Variante erfordert zwar mehr Berechnungsschritte (wegen des Aufwands für $!), aber damit lassen sich die Probleme mit Speicherbedarf
vermeiden und somit Ergebnisse für wesentlich grössere Bereiche erzielen:
foldl’ :: (a -> b -> a) -> a -> [b ] -> a
foldl’ f v [ ] = v
foldl’ f v (x : xs) = ((foldl’ f ) $! (f v x)) xs
303
WS 2006/2007, Programmierkonzepte und Modellierung (PKM), © Prof. Dr. D. Rösner; erstellt: 15. Januar 2007
304
Herunterladen