diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,11 @@
+# Changelog
+
+`fused-effects-mwc-random` uses [PVP Versioning][1].
+The changelog is available [on GitHub][2].
+
+## 0.0.0.0
+
+* Initially created.
+
+[1]: https://pvp.haskell.org
+[2]: https://github.com/patrickt/fused-effects-mwc-random/releases
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,29 @@
+BSD 3-Clause License
+
+Copyright (c) 2020, Patrick Thomson
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,12 @@
+# fused-effects-mwc-random
+
+[![Hackage](https://img.shields.io/hackage/v/fused-effects-mwc-random.svg?logo=haskell)](https://hackage.haskell.org/package/fused-effects-mwc-random)
+[![BSD3 license](https://img.shields.io/badge/license-BSD3-blue.svg)](LICENSE)
+
+High-quality uniformly-distributed pseudorandom number generation as an effect.
+
+This library provides a `Random` effect that piggybacks atop the `mwc-random` package, which produces high-quality random numbers in efficient time. A carrier type (`Control.Carrier.Random.Lifted`) encapsulates generator state and provides a convenient API to invoke system random number generation or pass a predefined seed. The `mwc-random` package is finely tuned; as such, this package should be an industrial-strength source of random numbers, suitable for tight loops.
+
+Please note that the [MWC-256](https://en.wikipedia.org/wiki/Multiply-with-carry_pseudorandom_number_generator) algorithm that underlies `mwc-random` is *not* cryptographically secure and should not be used for such purposes. Crypto code should use [`cryptonite`](https://hackage.haskell.org/package/cryptonite), as I'm sure you already know.
+
+For more advanced users, there exists also a module (`Control.Carrier.Random.Instances`) that provides the orphan instances required to use most `fused-effect` stacks with the `PrimMonad` machinery that powers `mwc-random`. This module is most useful when porting monad transformer stacks that already use the `mwc-random` API, or if you need to drop into the native `mwc-random` API.
diff --git a/bench/Bench.hs b/bench/Bench.hs
new file mode 100644
--- /dev/null
+++ b/bench/Bench.hs
@@ -0,0 +1,24 @@
+{-# LANGUAGE PackageImports #-}
+
+module Main (main) where
+
+import Control.Monad
+import Gauge
+
+import qualified "fused-effects-mwc-random" Control.Carrier.Random.Lifted as MWC
+import qualified "fused-effects-random" Control.Effect.Random as System
+
+mwc :: Int -> IO [Double]
+mwc n = MWC.runRandomSystem (replicateM n MWC.uniform)
+
+system :: Int -> IO [Double]
+system n = System.evalRandomIO (replicateM n System.getRandom)
+
+main :: IO ()
+main = defaultMain [ bench "System.Random (generate 1 double)" (nfAppIO system 1)
+                   , bench "MWC.Random (generate 1 double)" (nfAppIO mwc 1)
+                   , bench "System.Random (generate 10 double)" (nfAppIO system 10)
+                   , bench "MWC.Random (generate 10 double)" (nfAppIO mwc 10)
+                   , bench "System.Random (generate 100 double)" (nfAppIO system 100)
+                   , bench "MWC.Random (generate 100 double)" (nfAppIO mwc 100)
+                   ]
diff --git a/fused-effects-mwc-random.cabal b/fused-effects-mwc-random.cabal
new file mode 100644
--- /dev/null
+++ b/fused-effects-mwc-random.cabal
@@ -0,0 +1,79 @@
+cabal-version:       2.4
+name:                fused-effects-mwc-random
+version:             0.1.0.0
+synopsis:            High-quality random number generation as an effect.
+description:         This package wraps the mwc-random package and provides a convenient interface to invoke its functions from an effect stack.
+homepage:            https://github.com/fused-effects/fused-effects-mwc-random
+bug-reports:         https://github.com/fused-effects/fused-effects-mwc-random/issues
+license:             BSD-3-Clause
+license-file:        LICENSE
+author:              Patrick Thomson
+maintainer:          patrickt@github.com
+copyright:           2020 Patrick Thomson
+category:            Control
+build-type:          Simple
+extra-doc-files:     README.md
+                   , CHANGELOG.md
+tested-with:         GHC == 8.2.2
+                   , GHC == 8.4.4
+                   , GHC == 8.6.5
+                   , GHC == 8.8.1
+                   , GHC == 8.10.1
+
+common shared
+  ghc-options:         -Wall
+                       -Wincomplete-uni-patterns
+                       -Wincomplete-record-updates
+                       -Wcompat
+                       -Widentities
+                       -Wredundant-constraints
+                       -fhide-source-paths
+
+  if (impl(ghc >= 8.10))
+    ghc-options:       -Wno-missing-safe-haskell-mode
+                       -Wno-prepositive-qualified-module
+
+
+  default-language:    Haskell2010
+
+source-repository head
+  type:                git
+  location:            https://github.com/fused-effects/fused-effects-mwc-random.git
+
+library
+  import:              shared
+  hs-source-dirs:      src
+  exposed-modules:     Control.Carrier.Random.Lifted
+                     , Control.Carrier.Random.Instances
+                     , Control.Effect.Random
+
+
+  build-depends:       base >= 4.10 && < 4.15
+                     , fused-effects ^>= 1.1
+                     , mwc-random >= 0.13.6 && < 0.15
+                     , vector ^>= 0.12
+                     , primitive >= 0.6.4 && < 0.8
+                     , template-haskell >= 2.12
+                     , transformers >= 0.5.2 && < 0.6
+
+test-suite test
+  import:              shared
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      test
+  main-is:             Test.hs
+  other-modules:       Magic
+  build-depends:       base
+                     , fused-effects
+                     , fused-effects-mwc-random
+                     , mwc-random
+                     , vector
+
+benchmark bench
+  import: shared
+  type: exitcode-stdio-1.0
+  hs-source-dirs: bench
+  main-is: Bench.hs
+  build-depends: base
+               , gauge ^>= 0.2.5
+               , fused-effects-random
+               , fused-effects-mwc-random
diff --git a/src/Control/Carrier/Random/Instances.hs b/src/Control/Carrier/Random/Instances.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Carrier/Random/Instances.hs
@@ -0,0 +1,66 @@
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+
+-- | This module exists to export instances of @PrimMonad@ for the @fused-effects@
+-- ecosystem. These instances are trivially derivable, since all carrier types are
+-- monad transformers, but are boring to have to write by hand.
+--
+-- This module is most useful when porting monad transformer stacks that already use
+-- @mwc-random@ to the fused-effects ecosystem, or for when you have very
+-- fine-grained need to control the behavior or state of a random number generator.
+-- For new code, the 'Control.Effect.Random' effect will provide a more genial interface.
+module Control.Carrier.Random.Instances where
+
+import Control.Carrier.Choose.Church (ChooseC)
+import Control.Carrier.Cull.Church (CullC)
+import Control.Carrier.Cut.Church (CutC)
+import Control.Carrier.Empty.Maybe (EmptyC)
+import Control.Carrier.Error.Either (ErrorC)
+import Control.Carrier.Fail.Either (FailC)
+import Control.Carrier.Fresh.Strict (FreshC)
+import Control.Carrier.Lift (LiftC)
+import Control.Carrier.Reader (ReaderC)
+import qualified Control.Carrier.State.Lazy as Lazy
+import qualified Control.Carrier.State.Strict as Strict
+import Control.Carrier.Throw.Either (ThrowC)
+import Control.Carrier.Writer.Strict (WriterC)
+import Control.Monad
+import Control.Monad.Primitive
+import Control.Monad.Trans.Class
+import Data.Traversable
+import Language.Haskell.TH.Lib
+
+instance PrimMonad m => PrimMonad (LiftC m) where
+  type PrimState (LiftC m) = PrimState m
+  primitive = lift . primitive
+  {-# INLINE primitive #-}
+
+fmap
+  join
+  ( for
+      [''ChooseC, ''CullC, ''CutC, ''EmptyC, ''FailC, ''FreshC]
+      ( \c ->
+          [d|
+            instance PrimMonad m => PrimMonad ($(conT c) m) where
+              type PrimState ($(conT c) m) = PrimState m
+              primitive = lift . primitive
+              {-# INLINE primitive #-}
+            |]
+      )
+  )
+
+fmap
+  join
+  ( for
+      [''ReaderC, ''ErrorC, ''Strict.StateC, ''Lazy.StateC, ''ThrowC, ''WriterC]
+      ( \c ->
+          [d|
+            instance PrimMonad m => PrimMonad ($(conT c) r m) where
+              type PrimState ($(conT c) r m) = PrimState m
+              primitive = lift . primitive
+              {-# INLINE primitive #-}
+            |]
+      )
+  )
diff --git a/src/Control/Carrier/Random/Lifted.hs b/src/Control/Carrier/Random/Lifted.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Carrier/Random/Lifted.hs
@@ -0,0 +1,85 @@
+{-# LANGUAGE AllowAmbiguousTypes #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# OPTIONS_GHC -Wno-unused-imports #-}
+
+-- | This carrier lifts the internals of its random number generation into
+-- a 'LiftC' constraint, assuming the parameter to that 'LiftC' implements
+-- 'PrimMonad'. In practice, this means that your effect stack must terminate
+-- with @LiftC IO@ or @LiftC (ST s)@.
+module Control.Carrier.Random.Lifted
+  ( RandomC (..),
+    runRandomSystem,
+    runRandomSeeded,
+
+    -- * Random effect
+    module Control.Effect.Random,
+  )
+where
+
+import Control.Algebra
+import Control.Carrier.Lift
+import Control.Carrier.Reader
+import Control.Effect.Random
+import Control.Effect.Sum
+import Control.Monad.Fail
+import Control.Monad.IO.Class
+import Control.Monad.Primitive
+import qualified System.Random.MWC as MWC
+import qualified System.Random.MWC.Distributions as Dist
+
+newtype RandomC prim m a = RandomC {runRandomC :: ReaderC (MWC.Gen (PrimState prim)) m a}
+  deriving (Applicative, Functor, Monad, MonadFail, MonadIO)
+
+instance (Algebra sig m, Member (Lift n) sig, PrimMonad n) => Algebra (Random :+: sig) (RandomC n m) where
+  alg hdl sig ctx = do
+    gen <- RandomC ask
+    case sig of
+      L (Random dist) -> do
+        let act = case dist of
+              Uniform -> MWC.uniform
+              UniformR r -> MWC.uniformR r
+              Normal m d -> Dist.normal m d
+              Standard -> Dist.standard
+              Exponential s -> Dist.exponential s
+              TruncatedExp s r -> Dist.truncatedExp s r
+              Gamma s h -> Dist.gamma s h
+              ChiSquare d -> Dist.chiSquare d
+              Beta a b -> Dist.beta a b
+              Categorical w -> Dist.categorical w
+              LogCategorical lw -> Dist.logCategorical lw
+              Geometric0 p -> Dist.geometric0 p
+              Geometric1 p -> Dist.geometric1 p
+              Bernoulli p -> Dist.bernoulli p
+              Dirichlet t -> Dist.dirichlet t
+              Permutation n -> Dist.uniformPermutation n
+              Shuffle v -> Dist.uniformShuffle v
+        res <- sendM @n (act gen)
+        pure (res <$ ctx)
+      L Save -> do
+        res <- sendM @n (MWC.save gen)
+        pure (res <$ ctx)
+      R other -> RandomC (alg (runRandomC . hdl) (R other) ctx)
+  {-# INLINE alg #-}
+
+-- | Run a computation, seeding its random values from the system random number generator.
+--
+-- This is the de facto standard way to use this carrier. Keep in mind that seeding the RNG
+-- may be a computationally intensive process.
+runRandomSystem :: MonadIO m => RandomC IO m a -> m a
+runRandomSystem (RandomC act) = do
+  rand <- liftIO MWC.createSystemRandom
+  runReader rand act
+
+-- | Run a computation, seeding its random values from an existing 'MWC.Seed'.
+runRandomSeeded :: forall m n sig a. (Has (Lift n) sig m, PrimMonad n) => MWC.Seed -> RandomC n m a -> m a
+runRandomSeeded s (RandomC act) = do
+  rand <- sendM @n (MWC.restore s)
+  runReader rand act
diff --git a/src/Control/Effect/Random.hs b/src/Control/Effect/Random.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Effect/Random.hs
@@ -0,0 +1,251 @@
+{-# LANGUAGE DeriveFunctor #-}
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE StandaloneDeriving #-}
+
+-- | The @Random@ effect provides access to uniformly distributed random values of
+-- user-specified types or from well-known numerical distributions.
+--
+-- This is the “fancy” syntax that hides most details of randomness
+-- behind a nice API.
+module Control.Effect.Random
+  ( Random (..),
+
+    -- * Uniform distributions
+    uniform,
+    uniformR,
+
+    -- * Continuous distributions
+    normal,
+    standard,
+    exponential,
+    truncatedExp,
+    gamma,
+    chiSquare,
+    beta,
+
+    -- * Discrete distributions
+    categorical,
+    logCategorical,
+    geometric0,
+    geometric1,
+    bernoulli,
+    dirichlet,
+
+    -- * Permutations
+    uniformPermutation,
+    uniformShuffle,
+
+    -- * Introspection
+    save,
+    Distrib (..),
+
+    -- * Re-exports
+    MWC.Variate,
+    Has,
+  )
+where
+
+import Control.Algebra
+import Data.Kind
+import Data.Vector.Generic (Vector)
+import qualified System.Random.MWC as MWC
+
+-- | GADT representing the functions provided by mwc-random.
+data Distrib a where
+  Uniform :: MWC.Variate a => Distrib a
+  UniformR :: MWC.Variate a => (a, a) -> Distrib a
+  Normal :: Double -> Double -> Distrib Double
+  Standard :: Distrib Double
+  Exponential :: Double -> Distrib Double
+  TruncatedExp :: Double -> (Double, Double) -> Distrib Double
+  Gamma :: Double -> Double -> Distrib Double
+  ChiSquare :: Int -> Distrib Double
+  Beta :: Double -> Double -> Distrib Double
+  Categorical :: Vector v Double => v Double -> Distrib Int
+  LogCategorical :: Vector v Double => v Double -> Distrib Int
+  Geometric0 :: Double -> Distrib Int
+  Geometric1 :: Double -> Distrib Int
+  Bernoulli :: Double -> Distrib Bool
+  Dirichlet :: Traversable t => t Double -> Distrib (t Double)
+  Permutation :: Vector v Int => Int -> Distrib (v Int)
+  Shuffle :: Vector v a => v a -> Distrib (v a)
+
+data Random (m :: Type -> Type) k where
+  Random :: Distrib a -> Random m a
+  Save :: Random m MWC.Seed
+
+-- | Generate a single uniformly distributed random variate.  The
+-- range of values produced varies by type:
+--
+-- * For fixed-width integral types, the type's entire range is
+--   used.
+--
+-- * For floating point numbers, the range (0,1] is used. Zero is
+--   explicitly excluded, to allow variates to be used in
+--   statistical calculations that require non-zero values
+--   (e.g. uses of the 'log' function).
+--
+-- To generate a 'Float' variate with a range of [0,1), subtract
+-- 2**(-33).  To do the same with 'Double' variates, subtract
+-- 2**(-53).
+uniform :: (MWC.Variate a, Has Random sig m) => m a
+uniform = send (Random Uniform)
+{-# INLINE uniform #-}
+
+-- | Generate single uniformly distributed random variable in a
+-- given range.
+--
+-- * For integral types inclusive range is used.
+--
+-- * For floating point numbers range (a,b] is used if one ignores
+--   rounding errors.
+uniformR :: (MWC.Variate a, Has Random sig m) => (a, a) -> m a
+uniformR r = send (Random (UniformR r))
+{-# INLINE uniformR #-}
+
+-- | Generate a normally distributed random variate with given mean and standard deviation.
+normal ::
+  Has Random sig m =>
+  -- | Mean
+  Double ->
+  -- | Standard deviation
+  Double ->
+  m Double
+normal m d = send (Random (Normal m d))
+
+-- | Generate a normally distributed random variate with zero mean and unit variance.
+standard :: Has Random sig m => m Double
+standard = send (Random Standard)
+
+-- | Generate an exponentially distributed random variate.
+exponential ::
+  Has Random sig m =>
+  -- | Scale parameter
+  Double ->
+  m Double
+exponential s = send (Random (Exponential s))
+
+-- | Generate truncated exponentially distributed random variate.
+truncatedExp ::
+  Has Random sig m =>
+  -- | Scale parameter
+  Double ->
+  -- | Range to which distribution is
+  --   truncated. Values may be negative.
+  (Double, Double) ->
+  m (Double)
+truncatedExp s r = send (Random (TruncatedExp s r))
+
+-- | Random variate generator for gamma distribution.
+gamma ::
+  Has Random sig m =>
+  -- | Shape parameter
+  Double ->
+  -- | Scale parameter
+  Double ->
+  m Double
+gamma s d = send (Random (Gamma s d))
+
+-- | Random variate generator for the chi square distribution.
+chiSquare ::
+  Has Random sig m =>
+  -- | Number of degrees of freedom
+  Int ->
+  m Double
+chiSquare d = send (Random (ChiSquare d))
+
+-- | Random variate generator for the geometric distribution,
+-- computing the number of failures before success. Distribution's
+-- support is [0..].
+geometric0 ::
+  Has Random sig m =>
+  -- | /p/ success probability lies in (0,1]
+  Double ->
+  m Int
+geometric0 p = send (Random (Geometric0 p))
+
+-- | Random variate generator for geometric distribution for number of
+-- trials. Distribution's support is [1..] (i.e. just 'geometric0'
+-- shifted by 1).
+geometric1 ::
+  Has Random sig m =>
+  -- | /p/ success probability lies in (0,1]
+  Double ->
+  m Int
+geometric1 p = send (Random (Geometric1 p))
+
+-- | Random variate generator for Beta distribution
+beta ::
+  Has Random sig m =>
+  -- | alpha (>0)
+  Double ->
+  -- | beta  (>0)
+  Double ->
+  m Double
+beta a b = send (Random (Beta a b))
+{-# INLINE beta #-}
+
+-- | Random variate generator for Dirichlet distribution
+dirichlet ::
+  (Has Random sig m, Traversable t) =>
+  -- | container of parameters
+  t Double ->
+  m (t Double)
+{-# INLINE dirichlet #-}
+dirichlet t = send (Random (Dirichlet t))
+
+-- | Random variate generator for Bernoulli distribution
+bernoulli ::
+  Has Random sig m =>
+  -- | Probability of success (returning True)
+  Double ->
+  m Bool
+{-# INLINE bernoulli #-}
+bernoulli p = send (Random (Bernoulli p))
+
+-- | Random variate generator for categorical distribution.
+categorical ::
+  (Has Random sig m, Vector v Double) =>
+  -- | List of weights [>0]
+  v Double ->
+  m Int
+{-# INLINE categorical #-}
+categorical v = send (Random (Categorical v))
+
+-- | Random variate generator for categorical distribution where the
+--   weights are in the log domain. It's implemented in terms of
+--   'categorical'.
+logCategorical ::
+  (Has Random sig m, Vector v Double) =>
+  -- | List of logarithms of weights
+  v Double ->
+  m Int
+logCategorical v = send (Random (LogCategorical v))
+
+-- | Save the state of the random number generator to be used by subsequent
+-- carrier invocations.
+save :: Has Random sig m => m MWC.Seed
+save = send Save
+
+-- | Random variate generator for uniformly distributed permutations. It returns random permutation of vector [0 .. n-1]. This is the Fisher-Yates shuffle.
+uniformPermutation ::
+  (Has Random sig m, Vector v Int) =>
+  Int ->
+  m (v Int)
+uniformPermutation n = send (Random (Permutation n))
+
+-- | Random variate generator for a uniformly distributed shuffle (all
+--   shuffles are equiprobable) of a vector. It uses Fisher-Yates
+--   shuffle algorithm.
+--
+-- Implementation details prevent a native implementation of the 'MWC.uniformShuffleM'
+-- function. Use the native API if this is required.
+uniformShuffle ::
+  (Has Random sig m, Vector v a) =>
+  v a ->
+  m (v a)
+uniformShuffle n = send (Random (Shuffle n))
diff --git a/test/Magic.hs b/test/Magic.hs
new file mode 100644
--- /dev/null
+++ b/test/Magic.hs
@@ -0,0 +1,16 @@
+{-# LANGUAGE OverloadedLists, ScopedTypeVariables #-}
+
+module Magic (doit) where
+
+import           Control.Carrier.Lift
+import           Control.Carrier.Random.Instances ()
+import           Control.Carrier.Reader
+import           Control.Monad.IO.Class
+import qualified Data.Vector as Vector
+import qualified System.Random.MWC as MWC
+
+doit :: IO ()
+doit = runM $ runReader 'a' $ do
+  x <- MWC.initialize (Vector.fromList [1, 2,3])
+  (y :: Double) <- MWC.uniform x
+  liftIO $ print y
diff --git a/test/Test.hs b/test/Test.hs
new file mode 100644
--- /dev/null
+++ b/test/Test.hs
@@ -0,0 +1,15 @@
+{-# LANGUAGE TypeApplications #-}
+
+module Main where
+
+import Control.Carrier.Lift
+import Control.Carrier.Random.Lifted
+import Control.Monad.IO.Class
+import Data.Foldable
+import Magic
+
+main :: IO ()
+main = do
+  doit
+  runM . runRandomSystem $
+    for_ [(1 :: Int)..4] $ \_ -> uniform @Double >>= liftIO . print
