Look how one can watch the evaluation tree of a computation, to debug laziness-related problems.
{-# LANGUAGE BangPatterns #-}
module HTrace where
import Data.List (foldl')
import Data.IORef
import System.IO.Unsafe
level = unsafePerformIO $ newIORef 0
htrace str x = unsafePerformIO $ do
  lvl <- readIORef level
  putStrLn (replicate (4*lvl) ' ' ++ str)
  writeIORef level (lvl+1)
  let !vx = x
  writeIORef level lvl
  return vx
xs = map (\x -> htrace (show x) x) [1..10]
s = foldl (\a b -> htrace "+" (a+b)) 0 xs
s2 = foldl' (\a b -> htrace "+" (a+b)) 0 xs
b = htrace "b" 2
c = htrace "c" 3
a = htrace "a" $ b + c
x = htrace "x" $ b + c
*HTrace> a
a
    b
    c
5
*HTrace> x
x
5
*HTrace> s
+
    +
        +
            +
                +
                    +
                        +
                            +
                                +
                                    +
                                        1
                                    2
                                3
                            4
                        5
                    6
                7
            8
        9
    10
55
(reload)
*HTrace> s2
+
    1
+
    2
+
    3
+
    4
+
    5
+
    6
+
    7
+
    8
+
    9
+
    10
55
-- 
Eugene Kirpichov
Principal Engineer, Mirantis Inc. 
http://www.mirantis.com/Editor, 
http://fprog.ru/