diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2012-2015 Jared Tobin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/Numeric/MCMC/Metropolis.hs b/Numeric/MCMC/Metropolis.hs
new file mode 100644
--- /dev/null
+++ b/Numeric/MCMC/Metropolis.hs
@@ -0,0 +1,113 @@
+{-# OPTIONS_GHC -Wall #-}
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE RecordWildCards #-}
+
+-- |
+-- Module: Numeric.MCMC.Metropolis
+-- Copyright: (c) 2015 Jared Tobin
+-- License: MIT
+--
+-- Maintainer: Jared Tobin <jared@jtobin.ca>
+-- Stability: unstable
+-- Portability: ghc
+--
+-- This implementation uses spherical Gaussian proposals to implement a
+-- reliable and computationally inexpensive sampling routine.  It can be used
+-- as a baseline from which to benchmark other algorithms for a given problem.
+--
+-- The 'mcmc' function streams a trace to stdout to be processed elsewhere,
+-- while the `metropolis` transition can be used for more flexible purposes,
+-- such as working with samples in memory.
+
+module Numeric.MCMC.Metropolis (
+    mcmc
+  , metropolis
+
+  -- * Re-exported
+  , module Data.Sampling.Types
+  , MWC.create
+  , MWC.createSystemRandom
+  , MWC.withSystemRandom
+  , MWC.asGenIO
+  ) where
+
+import Control.Monad (when)
+import Control.Monad.Primitive (PrimMonad, PrimState)
+import Control.Monad.Trans.Class (lift)
+import Control.Monad.Trans.State.Strict (execStateT, get, put)
+import Data.Sampling.Types (Target(..), Chain(..), Transition)
+#if __GLASGOW_HASKELL__ < 710
+import Data.Traversable (Traversable, traverse)
+#endif
+import GHC.Prim (RealWorld)
+import Pipes (Producer, yield, (>->), runEffect)
+import qualified Pipes.Prelude as Pipes (mapM_, take)
+import System.Random.MWC.Probability (Gen, Prob)
+import qualified System.Random.MWC.Probability as MWC
+
+-- Propose a state transition according to a Gaussian proposal distribution
+-- with the specified standard deviation.
+propose
+  :: (PrimMonad m, Traversable f)
+  => Double
+  -> f Double
+  -> Prob m (f Double)
+propose radial = traverse perturb where
+  perturb m = MWC.normal m radial
+
+-- | A generic Metropolis transition operator.
+metropolis
+  :: (Traversable f, PrimMonad m)
+  => Double
+  -> Transition m (Chain (f Double) b)
+metropolis radial = do
+  Chain {..} <- get
+  proposal <- lift (propose radial chainPosition)
+  let proposalScore = lTarget chainTarget proposal
+      acceptProb    = whenNaN 0 (exp (min 0 (proposalScore - chainScore)))
+
+  accept <- lift (MWC.bernoulli acceptProb)
+  when accept (put (Chain chainTarget proposalScore proposal chainTunables))
+
+-- A Markov chain driven by the Metropolis transition operator.
+chain
+  :: (Traversable f, PrimMonad m)
+  => Double
+  -> Chain (f Double) b
+  -> Gen (PrimState m)
+  -> Producer (Chain (f Double) b) m ()
+chain radial = loop where
+  loop state prng = do
+    next <- lift (MWC.sample (execStateT (metropolis radial) state) prng)
+    yield next
+    loop next prng
+
+-- | Trace 'n' iterations of a Markov chain and stream them to stdout.
+--
+-- >>> let rosenbrock [x0, x1] = negate (5  *(x1 - x0 ^ 2) ^ 2 + 0.05 * (1 - x0) ^ 2)
+-- >>> withSystemRandom . asGenIO $ mcmc 3 1 [0, 0] rosenbrock
+-- 0.5000462419822702,0.5693944056267897
+-- 0.5000462419822702,0.5693944056267897
+-- -0.7525995304580824,1.2240725505283248
+mcmc
+  :: (Traversable f, Show (f Double))
+  => Int
+  -> Double
+  -> f Double
+  -> (f Double -> Double)
+  -> Gen RealWorld
+  -> IO ()
+mcmc n radial chainPosition target gen = runEffect $
+        chain radial Chain {..} gen
+    >-> Pipes.take n
+    >-> Pipes.mapM_ print
+  where
+    chainScore    = lTarget chainTarget chainPosition
+    chainTunables = Nothing
+    chainTarget   = Target target Nothing
+
+-- Use a provided default value when the argument is NaN.
+whenNaN :: RealFloat a => a -> a -> a
+whenNaN val x
+  | isNaN x   = val
+  | otherwise = x
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/mighty-metropolis.cabal b/mighty-metropolis.cabal
new file mode 100644
--- /dev/null
+++ b/mighty-metropolis.cabal
@@ -0,0 +1,72 @@
+name:                mighty-metropolis
+version:             1.0.0
+synopsis:            The Metropolis algorithm.
+homepage:            http://github.com/jtobin/mighty-metropolis
+license:             MIT
+license-file:        LICENSE
+author:              Jared Tobin
+maintainer:          jared@jtobin.ca
+category:            Numeric
+build-type:          Simple
+cabal-version:       >= 1.10
+description:
+  The classic Metropolis algorithm.
+  .
+  Wander around parameter space according to a simple spherical Gaussian
+  distribution.
+  .
+  Exports a 'mcmc' function that prints a trace to stdout, as well as a
+  'metropolis' transition operator that can be used more generally.
+  .
+  > import Numeric.MCMC.Metropolis
+  >
+  > rosenbrock :: [Double] -> Double
+  > rosenbrock [x0, x1] = negate (5  *(x1 - x0 ^ 2) ^ 2 + 0.05 * (1 - x0) ^ 2)
+  >
+  > main :: IO ()
+  > main = withSystemRandom . asGenIO $ mcmc 10000 1 [0, 0] rosenbrock
+
+Source-repository head
+  Type:     git
+  Location: http://github.com/jtobin/mighty-metropolis.git
+
+library
+  default-language:    Haskell2010
+  ghc-options:
+      -Wall
+  exposed-modules:
+      Numeric.MCMC.Metropolis
+  build-depends:
+      base             < 5
+    , ghc-prim
+    , pipes
+    , primitive
+    , mcmc-types       >= 1.0.1
+    , mwc-probability  >= 1.0.1
+    , transformers
+
+Test-suite rosenbrock
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      test
+  main-is:             Rosenbrock.hs
+  default-language:    Haskell2010
+  ghc-options:
+    -rtsopts
+  build-depends:
+      base              < 5
+    , mighty-metropolis
+    , mwc-probability   >= 1.0.1
+
+Test-suite bnn
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      test
+  main-is:             BNN.hs
+  default-language:    Haskell2010
+  ghc-options:
+    -rtsopts
+  build-depends:
+      base              < 5
+    , containers
+    , mighty-metropolis
+    , mwc-probability   >= 1.0.1
+
diff --git a/test/BNN.hs b/test/BNN.hs
new file mode 100644
--- /dev/null
+++ b/test/BNN.hs
@@ -0,0 +1,15 @@
+{-# OPTIONS_GHC -fno-warn-type-defaults #-}
+
+module Main where
+
+import Numeric.MCMC.Metropolis
+import Data.Sequence (Seq, fromList, index)
+
+bnn :: Seq Double -> Double
+bnn xs = -0.5 * (x0 ^ 2 * x1 ^ 2 + x0 ^ 2 + x1 ^ 2 - 8 * x0 - 8 * x1) where
+  x0 = index xs 0
+  x1 = index xs 1
+
+main :: IO ()
+main = withSystemRandom . asGenIO $ mcmc 10000 1 (fromList [0, 0]) bnn
+
diff --git a/test/Rosenbrock.hs b/test/Rosenbrock.hs
new file mode 100644
--- /dev/null
+++ b/test/Rosenbrock.hs
@@ -0,0 +1,12 @@
+{-# OPTIONS_GHC -fno-warn-type-defaults #-}
+
+module Main where
+
+import Numeric.MCMC.Metropolis
+
+rosenbrock :: [Double] -> Double
+rosenbrock [x0, x1] = negate (5  *(x1 - x0 ^ 2) ^ 2 + 0.05 * (1 - x0) ^ 2)
+
+main :: IO ()
+main = withSystemRandom . asGenIO $ mcmc 10000 1 [0, 0] rosenbrock
+
