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