diff --git a/Criterion.hs b/Criterion.hs
--- a/Criterion.hs
+++ b/Criterion.hs
@@ -1,6 +1,6 @@
 -- |
 -- Module      : Criterion
--- Copyright   : (c) Bryan O'Sullivan 2009
+-- Copyright   : (c) 2009, 2010 Bryan O'Sullivan
 --
 -- License     : BSD-style
 -- Maintainer  : bos@serpentine.com
@@ -15,8 +15,9 @@
     , Benchmark
     , Pure
     , nf
-    , nfIO
     , whnf
+    , nfIO
+    , whnfIO
     , bench
     , bgroup
     , runBenchmark
@@ -34,15 +35,15 @@
 import Criterion.Monad (Criterion, getConfig, getConfigItem)
 import Criterion.Plot (plotWith, plotKDE, plotTiming)
 import Criterion.Types (Benchmarkable(..), Benchmark(..), Pure,
-                        bench, bgroup, nf, nfIO, whnf)
-import Data.Array.Vector ((:*:)(..), concatU, lengthU, mapU)
-import Statistics.Function (createIO, minMax)
+                        bench, bgroup, nf, nfIO, whnf, whnfIO)
+import qualified Data.Vector.Unboxed as U
+import Statistics.Function (create, minMax)
 import Statistics.KernelDensity (epanechnikovPDF)
-import Statistics.RandomVariate (withSystemRandom)
-import Statistics.Resampling (resample)
+import Statistics.Resampling (Resample, resample)
 import Statistics.Resampling.Bootstrap (Estimate(..), bootstrapBCA)
 import Statistics.Sample (mean, stdDev)
 import Statistics.Types (Sample)
+import System.Random.MWC (withSystemRandom)
 import System.Mem (performGC)
 import Text.Printf (printf)
 
@@ -52,8 +53,7 @@
 runBenchmark env b = do
   liftIO $ runForAtLeast 0.1 10000 (`replicateM_` getTime)
   let minTime = envClockResolution env * 1000
-  (testTime :*: testIters :*: _) <-
-      liftIO $ runForAtLeast (min minTime 0.1) 1 (run b)
+  (testTime, testIters, _) <- liftIO $ runForAtLeast (min minTime 0.1) 1 (run b)
   prolix "ran %d iterations in %s\n" testIters (secs testTime)
   cfg <- getConfig
   let newIters    = ceiling $ minTime * testItersD / testTime
@@ -63,8 +63,8 @@
   note "collecting %d samples, %d iterations each, in estimated %s\n"
        sampleCount newIters (secs (fromIntegral sampleCount * newItersD *
                                    testTime / testItersD))
-  times <- liftIO . fmap (mapU ((/ newItersD) . subtract (envClockCost env))) .
-           createIO sampleCount . const $ do
+  times <- liftIO . fmap (U.map ((/ newItersD) . subtract (envClockCost env))) .
+           create sampleCount . const $ do
              when (fromLJ cfgPerformGC cfg) $ performGC
              time_ (run b newIters)
   return times
@@ -74,11 +74,12 @@
                  -> Criterion Sample
 runAndAnalyseOne env _desc b = do
   times <- runBenchmark env b
-  let numSamples = lengthU times
+  let numSamples = U.length times
   let ests = [mean,stdDev]
   numResamples <- getConfigItem $ fromLJ cfgResamples
   note "bootstrapping with %d resamples\n" numResamples
-  res <- liftIO $ withSystemRandom (\gen -> resample gen ests numResamples times)
+  res <- liftIO . withSystemRandom $ \gen ->
+         resample gen ests numResamples times :: IO [Resample]
   ci <- getConfigItem $ fromLJ cfgConfInterval
   let [em,es] = bootstrapBCA ci times ests res
       (effect, v) = outlierVariance em es (fromIntegral $ numSamples)
@@ -113,7 +114,8 @@
     extremes = case descTimes of
                  (_:_:_) -> toJust . minMax . concatU . map snd $ descTimes
                  _       -> Nothing
-    toJust r@(lo :*: hi)
+    concatU = foldr (U.++) U.empty
+    toJust r@(lo, hi)
         | lo == infinity || hi == -infinity = Nothing
         | otherwise                         = Just r
         where infinity                      = 1/0
diff --git a/Criterion/Analysis.hs b/Criterion/Analysis.hs
--- a/Criterion/Analysis.hs
+++ b/Criterion/Analysis.hs
@@ -1,6 +1,6 @@
 -- |
 -- Module      : Criterion.Analysis
--- Copyright   : (c) Bryan O'Sullivan 2009
+-- Copyright   : (c) 2009, 2010 Bryan O'Sullivan
 --
 -- License     : BSD-style
 -- Maintainer  : bos@serpentine.com
@@ -24,7 +24,7 @@
 import Criterion.IO (note)
 import Criterion.Measurement (secs)
 import Criterion.Monad (Criterion)
-import Data.Array.Vector (foldlU)
+import qualified Data.Vector.Unboxed as U
 import Data.Int (Int64)
 import Data.Monoid (Monoid(..))
 import Statistics.Function (sort)
@@ -67,7 +67,7 @@
 
 -- | Classify outliers in a data set, using the boxplot technique.
 classifyOutliers :: Sample -> Outliers
-classifyOutliers sa = foldlU ((. outlier) . mappend) mempty ssa
+classifyOutliers sa = U.foldl ((. outlier) . mappend) mempty ssa
     where outlier e = Outliers {
                         samplesSeen = 1
                       , lowSevere = if e <= loS then 1 else 0
diff --git a/Criterion/Config.hs b/Criterion/Config.hs
--- a/Criterion/Config.hs
+++ b/Criterion/Config.hs
@@ -2,7 +2,7 @@
 
 -- |
 -- Module      : Criterion.Config
--- Copyright   : (c) Bryan O'Sullivan 2009
+-- Copyright   : (c) 2009, 2010 Bryan O'Sullivan
 --
 -- License     : BSD-style
 -- Maintainer  : bos@serpentine.com
diff --git a/Criterion/Environment.hs b/Criterion/Environment.hs
--- a/Criterion/Environment.hs
+++ b/Criterion/Environment.hs
@@ -2,7 +2,7 @@
 
 -- |
 -- Module      : Criterion.Environment
--- Copyright   : (c) Bryan O'Sullivan 2009
+-- Copyright   : (c) 2009, 2010 Bryan O'Sullivan
 --
 -- License     : BSD-style
 -- Maintainer  : bos@serpentine.com
@@ -23,9 +23,9 @@
 import Criterion.IO (note)
 import Criterion.Measurement (getTime, runForAtLeast, time_)
 import Criterion.Monad (Criterion)
-import Data.Array.Vector
+import qualified Data.Vector.Unboxed as U
 import Data.Typeable (Typeable)
-import Statistics.Function (createIO)
+import Statistics.Function (create)
 
 -- | Measured aspects of the execution environment.
 data Environment = Environment {
@@ -39,7 +39,7 @@
 measureEnvironment :: Criterion Environment
 measureEnvironment = do
   note "warming up\n"
-  (_ :*: seed :*: _) <- liftIO $ runForAtLeast 0.1 10000 resolution
+  (_, seed, _) <- liftIO $ runForAtLeast 0.1 10000 resolution
   note "estimating clock resolution...\n"
   clockRes <- thd3 `fmap` liftIO (runForAtLeast 0.5 seed resolution) >>=
               uncurry analyseMean
@@ -51,13 +51,13 @@
              }
   where
     resolution k = do
-      times <- createIO (k+1) (const getTime)
-      return (tailU . filterU (>=0) . zipWithU (-) (tailU times) $ times,
-              lengthU times)
+      times <- create (k+1) (const getTime)
+      return (U.tail . U.filter (>=0) . U.zipWith (-) (U.tail times) $ times,
+              U.length times)
     cost timeLimit = liftIO $ do
       let timeClock k = time_ (replicateM_ k getTime)
       timeClock 1
-      (_ :*: iters :*: elapsed) <- runForAtLeast 0.01 10000 timeClock
-      times <- createIO (ceiling (timeLimit / elapsed)) $ \_ -> timeClock iters
-      return (mapU (/ fromIntegral iters) times, lengthU times)
-    thd3 (_ :*: _:*: c) = c
+      (_, iters, elapsed) <- runForAtLeast 0.01 10000 timeClock
+      times <- create (ceiling (timeLimit / elapsed)) $ \_ -> timeClock iters
+      return (U.map (/ fromIntegral iters) times, U.length times)
+    thd3 (_, _, c) = c
diff --git a/Criterion/IO.hs b/Criterion/IO.hs
--- a/Criterion/IO.hs
+++ b/Criterion/IO.hs
@@ -1,6 +1,6 @@
 -- |
 -- Module      : Criterion.IO
--- Copyright   : (c) Bryan O'Sullivan 2009
+-- Copyright   : (c) 2009, 2010 Bryan O'Sullivan
 --
 -- License     : BSD-style
 -- Maintainer  : bos@serpentine.com
diff --git a/Criterion/Main.hs b/Criterion/Main.hs
--- a/Criterion/Main.hs
+++ b/Criterion/Main.hs
@@ -1,6 +1,6 @@
 -- |
 -- Module      : Criterion.Main
--- Copyright   : (c) Bryan O'Sullivan 2009
+-- Copyright   : (c) 2009, 2010 Bryan O'Sullivan
 --
 -- License     : BSD-style
 -- Maintainer  : bos@serpentine.com
@@ -32,8 +32,9 @@
     , bench
     , bgroup
     , nf
-    , nfIO
     , whnf
+    , nfIO
+    , whnfIO
     -- * Running benchmarks
     , defaultMain
     , defaultMainWith
@@ -51,13 +52,14 @@
 import Criterion.MultiMap (singleton)
 import Criterion.Monad (Criterion, withConfig)
 import Criterion.Types (Benchmarkable(..), Benchmark(..), Pure, bench,
-                        benchNames, bgroup, nf, nfIO, whnf)
+                        benchNames, bgroup, nf, nfIO, whnf, whnfIO)
 import Data.List (isPrefixOf, sort)
 import Data.Monoid (Monoid(..), Last(..))
 import System.Console.GetOpt
 import System.Environment (getArgs, getProgName)
 import System.Exit (ExitCode(..), exitWith)
-import Text.ParserCombinators.Parsec
+import Text.Parsec
+import Text.Parsec.String
 
 -- | Parse a plot output.
 parsePlot :: Parser PlotOutput
@@ -197,9 +199,9 @@
 -- > fib n = fib (n-1) + fib (n-2)
 -- >
 -- > main = defaultMain [
--- >        bgroup "fib" [ bench "fib 10" $ B fib 10
--- >                     , bench "fib 35" $ B fib 35
--- >                     , bench "fib 37" $ B fib 37
+-- >        bgroup "fib" [ bench "10" $ whnf fib 10
+-- >                     , bench "35" $ whnf fib 35
+-- >                     , bench "37" $ whnf fib 37
 -- >                     ]
 -- >                    ]
 defaultMain :: [Benchmark] -> IO ()
@@ -219,7 +221,7 @@
 -- >            }
 -- > 
 -- > main = defaultMainWith myConfig (return ()) [
--- >          bench "fib 30" $ B fib 30
+-- >          bench "fib 30" $ whnf fib 30
 -- >        ]
 --
 -- If you save the above example as @\"Fib.hs\"@, you should be able
diff --git a/Criterion/Measurement.hs b/Criterion/Measurement.hs
--- a/Criterion/Measurement.hs
+++ b/Criterion/Measurement.hs
@@ -1,5 +1,16 @@
 {-# LANGUAGE BangPatterns, ScopedTypeVariables, TypeOperators #-}
 
+-- |
+-- Module      : Criterion.Measurement
+-- Copyright   : (c) 2009, 2010 Bryan O'Sullivan
+--
+-- License     : BSD-style
+-- Maintainer  : bos@serpentine.com
+-- Stability   : experimental
+-- Portability : GHC
+--
+-- Benchmark measurement code.
+
 module Criterion.Measurement
     (
       getTime
@@ -10,16 +21,16 @@
     ) where
     
 import Control.Monad (when)
-import Data.Array.Vector ((:*:)(..))
 import Data.Time.Clock.POSIX (getPOSIXTime)
 import Text.Printf (printf)
         
-time :: IO a -> IO (Double :*: a)
+time :: IO a -> IO (Double, a)
 time act = do
   start <- getTime
   result <- act
   end <- getTime
-  return (end - start :*: result)
+  let !delta = end - start
+  return (delta, result)
 
 time_ :: IO a -> IO Double
 time_ act = do
@@ -31,17 +42,17 @@
 getTime :: IO Double
 getTime = (fromRational . toRational) `fmap` getPOSIXTime
 
-runForAtLeast :: Double -> Int -> (Int -> IO a) -> IO (Double :*: Int :*: a)
+runForAtLeast :: Double -> Int -> (Int -> IO a) -> IO (Double, Int, a)
 runForAtLeast howLong initSeed act = loop initSeed (0::Int) =<< getTime
   where
     loop !seed !iters initTime = do
       now <- getTime
       when (now - initTime > howLong * 10) $
         fail (printf "took too long to run: seed %d, iters %d" seed iters)
-      elapsed :*: result <- time (act seed)
+      (elapsed,result) <- time (act seed)
       if elapsed < howLong
         then loop (seed * 2) (iters+1) initTime
-        else return (elapsed :*: seed :*: result)
+        else return (elapsed, seed, result)
 
 secs :: Double -> String
 secs k
diff --git a/Criterion/Monad.hs b/Criterion/Monad.hs
--- a/Criterion/Monad.hs
+++ b/Criterion/Monad.hs
@@ -1,7 +1,7 @@
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 -- |
 -- Module      : Criterion.Monad
--- Copyright   : (c) Neil Brown 2009
+-- Copyright   : (c) 2009 Neil Brown
 --
 -- License     : BSD-style
 -- Maintainer  : bos@serpentine.com
diff --git a/Criterion/Plot.hs b/Criterion/Plot.hs
--- a/Criterion/Plot.hs
+++ b/Criterion/Plot.hs
@@ -2,7 +2,7 @@
 
 -- |
 -- Module      : Criterion.Plot
--- Copyright   : (c) Bryan O'Sullivan 2009
+-- Copyright   : (c) 2009, 2010 Bryan O'Sullivan
 --
 -- License     : BSD-style
 -- Maintainer  : bos@serpentine.com
@@ -21,11 +21,12 @@
 import Control.Monad.Trans (liftIO)
 import Criterion.Config
 import Criterion.Monad (Criterion, getConfigItem)
-import Data.Array.Vector
+import qualified Data.Vector.Unboxed as U
 import Data.Char (isSpace, toLower)
 import Data.Foldable (forM_)
 import Data.List (group, intersperse)
 import Statistics.KernelDensity (Points, fromPoints)
+import Statistics.Function (indexed)
 import Statistics.Types (Sample)
 import System.FilePath (pathSeparator)
 import System.IO (IOMode(..), Handle, hPutStr, withBinaryFile)
@@ -53,7 +54,7 @@
 plotTiming CSV desc times = do
   writeTo (mangle $ printf "%s timings.csv" desc) $ \h -> do
     putRow h ["sample", "execution time"]
-    forM_ (fromU $ indexedU times) $ \(x :*: y) ->
+    forM_ (U.toList $ indexed times) $ \(x,y) ->
       putRow h [show x, show y]
 
 #ifdef HAVE_CHART
@@ -80,15 +81,15 @@
 -- | Plot kernel density estimate.
 plotKDE :: PlotOutput           -- ^ The kind of output desired.
         -> String               -- ^ Benchmark name.
-        -> Maybe (Double :*: Double) -- ^ Range of x-axis
+        -> Maybe (Double, Double) -- ^ Range of x-axis
         -> Points               -- ^ Points at which KDE was computed.
-        -> UArr Double          -- ^ Kernel density estimates.
+        -> U.Vector Double      -- ^ Kernel density estimates.
         -> IO ()
 
 plotKDE CSV desc _exs points pdf = do
   writeTo (mangle $ printf "%s densities.csv" desc) $ \h -> do
     putRow h ["execution time", "probability"]
-    forM_ (zip (fromU pdf) (fromU (fromPoints points))) $ \(x, y) ->
+    forM_ (zip (U.toList pdf) (U.toList (fromPoints points))) $ \(x, y) ->
       putRow h [show x, show y]
 
 #ifdef HAVE_CHART
diff --git a/Criterion/Types.hs b/Criterion/Types.hs
--- a/Criterion/Types.hs
+++ b/Criterion/Types.hs
@@ -3,7 +3,7 @@
 
 -- |
 -- Module      : Criterion.Types
--- Copyright   : (c) Bryan O'Sullivan 2009
+-- Copyright   : (c) 2009, 2010 Bryan O'Sullivan
 --
 -- License     : BSD-style
 -- Maintainer  : bos@serpentine.com
@@ -32,6 +32,7 @@
     , whnf
     , nf
     , nfIO
+    , whnfIO
     , bench
     , bgroup
     , benchNames
@@ -69,8 +70,15 @@
 -- This is particularly useful for forcing a lazy IO action to be
 -- completely performed.
 nfIO :: NFData a => IO a -> IO ()
-nfIO a = a >>= \k -> return $! rnf k
+nfIO a = evaluate . rnf =<< a
 {-# INLINE nfIO #-}
+
+-- | Perform an action, then evaluate its result to weak head normal
+-- form (WHNF).  This is useful for forcing an IO action whose result
+-- is an expression to be evaluated down to a more useful value.
+whnfIO :: NFData a => IO a -> IO ()
+whnfIO a = a >>= evaluate >> return ()
+{-# INLINE whnfIO #-}
 
 instance Benchmarkable Pure where
     run p@(WHNF _ _) = go p
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2009, Bryan O'Sullivan
+Copyright (c) 2009, 2010 Bryan O'Sullivan
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/criterion.cabal b/criterion.cabal
--- a/criterion.cabal
+++ b/criterion.cabal
@@ -1,11 +1,11 @@
 name:           criterion
-version:        0.4.1.0
+version:        0.5.0.0
 synopsis:       Robust, reliable performance measurement and analysis
 license:        BSD3
 license-file:   LICENSE
 author:         Bryan O'Sullivan <bos@serpentine.com>
 maintainer:     Bryan O'Sullivan <bos@serpentine.com>
-copyright:      2009 Bryan O'Sullivan
+copyright:      2009-2010 Bryan O'Sullivan
 category:       Development, Performance, Testing
 build-type:     Simple
 cabal-version:  >= 1.2
@@ -26,7 +26,9 @@
   examples in the Criterion.Main module.
 
 flag Chart
-  Description: enable use of the Chart package
+  description: enable use of the Chart package
+  -- Broken under GHC 6.12 so far.
+  default: False
 
 library
   exposed-modules:
@@ -49,16 +51,17 @@
     deepseq >= 1.1.0.0,
     filepath,
     mtl,
+    mwc-random >= 0.5.0.0,
     parallel,
-    parsec,
-    statistics >= 0.3.5,
+    parsec >= 3.1.0,
+    statistics >= 0.5.1.0,
     time,
-    uvector >= 0.1.0.5,
-    uvector-algorithms >= 0.2
+    vector >= 0.5,
+    vector-algorithms >= 0.3
 
   if flag(chart)
     build-depends:
-      Chart>=0.12,
+      Chart >= 0.12,
       data-accessor
     cpp-options: -DHAVE_CHART
 
@@ -68,3 +71,5 @@
   ghc-options: -Wall -funbox-strict-fields -O2
   if impl(ghc >= 6.8)
     ghc-options: -fwarn-tabs
+  if impl(ghc >= 6.12)
+    ghc-options: -fno-warn-unused-do-bind
