diff --git a/flat-mcmc.cabal b/flat-mcmc.cabal
--- a/flat-mcmc.cabal
+++ b/flat-mcmc.cabal
@@ -1,5 +1,5 @@
 name:                flat-mcmc
-version:             1.2.2
+version:             1.3.0
 synopsis:            Painless general-purpose sampling.
 homepage:            https://github.com/jtobin/flat-mcmc
 license:             MIT
@@ -59,10 +59,10 @@
     , monad-par        >= 0.3.4.7 && < 1
     , monad-par-extras >= 0.3.3 && < 1
     , mwc-probability  >= 1.0.1 && < 2
-    , pipes            >  4     && < 5
-    , primitive
-    , text
-    , transformers
+    , pipes            >= 4     && < 5
+    , primitive        >= 0.6   && < 1
+    , text             >= 1.2   && < 2
+    , transformers     >= 0.2   && < 0.6
     , vector           >= 0.10  && < 1
 
 Test-suite rosenbrock
@@ -84,6 +84,17 @@
   default-language:    Haskell2010
   ghc-options:
     -rtsopts -threaded
+  build-depends:
+      base
+    , flat-mcmc
+    , vector
+
+executable bnn-example
+  hs-source-dirs:      src
+  main-is:             Main.hs
+  default-language:    Haskell2010
+  ghc-options:
+    -O2 -Wall -rtsopts -threaded
   build-depends:
       base
     , flat-mcmc
diff --git a/lib/Numeric/MCMC/Flat.hs b/lib/Numeric/MCMC/Flat.hs
--- a/lib/Numeric/MCMC/Flat.hs
+++ b/lib/Numeric/MCMC/Flat.hs
@@ -1,4 +1,5 @@
 {-# OPTIONS_GHC -fno-warn-type-defaults #-}
+{-# LANGUAGE BangPatterns #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RecordWildCards #-}
 
@@ -39,8 +40,8 @@
 
 import Control.Monad (replicateM)
 import Control.Monad.Par (NFData)
-import Control.Monad.Par.Scheds.Direct hiding (put, get)
 import Control.Monad.Par.Combinator (parMap)
+import Control.Monad.Par.Scheds.Sparks hiding (get)
 import Control.Monad.Primitive (PrimMonad, PrimState, RealWorld)
 import Control.Monad.Trans.State.Strict (get, put, execStateT)
 import Data.Monoid
@@ -104,8 +105,8 @@
 {-# INLINE acceptProb #-}
 
 move :: Target Particle -> Particle -> Particle -> Double -> Double -> Particle
-move target p0 p1 z zc =
-  let proposal = stretch p0 p1 z
+move target !p0 p1 z zc =
+  let !proposal = stretch p0 p1 z
       pAccept  = acceptProb target p0 proposal z
   in  if   zc <= min 1 (exp pAccept)
       then proposal
@@ -122,17 +123,16 @@
 execute target e0 e1 n = do
   zs  <- replicateM n symmetric
   zcs <- replicateM n uniform
-  vjs <- replicateM n (uniformR (1, n))
+  js  <- U.replicateM n (uniformR (1, n))
 
   let granularity = truncate (fromIntegral n / 2)
 
-      js      = U.fromList vjs
       w0 k    = e0 `V.unsafeIndex` pred k
       w1 k ks = e1 `V.unsafeIndex` pred (ks `U.unsafeIndex` pred k)
 
 
       worker (k, z, zc) = move target (w0 k) (w1 k js) z zc
-      result = runPar $
+      !result = runPar $
         parMapChunk granularity worker (zip3 [1..n] zs zcs)
 
   return $! V.fromList result
@@ -151,8 +151,8 @@
       e1   = V.unsafeSlice n n chainPosition
   result0 <- lift (execute chainTarget e0 e1 n)
   result1 <- lift (execute chainTarget e1 result0 n)
-  let ensemble = V.concat [result0, result1]
-  put (Chain chainTarget ensemble)
+  let !ensemble = V.concat [result0, result1]
+  put $! (Chain chainTarget ensemble)
 {-# INLINE flat #-}
 
 chain :: PrimMonad m => Chain -> Gen (PrimState m) -> Producer Chain m ()
diff --git a/src/Main.hs b/src/Main.hs
new file mode 100644
--- /dev/null
+++ b/src/Main.hs
@@ -0,0 +1,23 @@
+{-# OPTIONS_GHC -fno-warn-type-defaults #-}
+
+module Main where
+
+import Numeric.MCMC.Flat
+import qualified Data.Vector.Unboxed as U (toList, fromList)
+import qualified Data.Vector as V (fromList)
+
+bnn :: Particle -> Double
+bnn xs = -0.5 * (x0 ^ 2 * x1 ^ 2 + x0 ^ 2 + x1 ^ 2 - 8 * x0 - 8 * x1) where
+  [x0, x1] = U.toList xs
+
+ensemble :: Ensemble
+ensemble = V.fromList [
+    U.fromList [negate 1.0, negate 1.0]
+  , U.fromList [negate 1.0, 1.0]
+  , U.fromList [1.0, negate 1.0]
+  , U.fromList [1.0, 1.0]
+  ]
+
+main :: IO ()
+main = withSystemRandom . asGenIO $ mcmc 10000 ensemble bnn
+
