diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Sam Rijs
+
+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/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/random-hypergeometric.cabal b/random-hypergeometric.cabal
new file mode 100644
--- /dev/null
+++ b/random-hypergeometric.cabal
@@ -0,0 +1,41 @@
+name:                random-hypergeometric
+version:             0.1.0.0
+synopsis:            Random variate generation from hypergeometric distributions
+description:         The Hypergeometric distribution.  This is the discrete probability
+                     distribution that measures the probability of /k/ successes in /l/
+                     trials, without replacement, from a finite population.
+homepage:            https://github.com/srijs/random-hypergeometric
+license:             MIT
+license-file:        LICENSE
+author:              Sam Rijs
+maintainer:          srijs@airpost.net
+copyright:           2015 Sam Rijs
+                     2005 Robert Kern
+                     1998 Ivan Frohne
+category:            Math
+build-type:          Simple
+cabal-version:       >=1.10
+
+library
+  exposed-modules:     Data.Random.Distribution.Hypergeometric
+  other-modules:       Data.Random.Distribution.Hypergeometric.Impl
+  build-depends:       base >=4.7 && <4.8,
+                       random-fu >=0.2 && <0.3,
+                       math-functions >=0.1 && <0.2
+  hs-source-dirs:      src
+  default-language:    Haskell2010
+
+test-suite test
+  type:           detailed-0.9
+  test-module:    Data.Random.Distribution.Hypergeometric.Test
+  other-modules:  Data.Random.Distribution.Hypergeometric,
+                  Data.Random.Distribution.Hypergeometric.Impl
+  build-depends:  base                  >=4.7 && <4.8,
+                  Cabal                 >=1.10,
+                  random-fu             >=0.2 && <0.3,
+                  math-functions        >=0.1 && <0.2,
+                  mwc-random            >=0.13 && <0.14,
+                  vector                >=0.10 && <0.11,
+                  QuickCheck            >=2.7 && <2.8,
+                  cabal-test-quickcheck >=0.1 && <0.2
+  hs-source-dirs: src
diff --git a/src/Data/Random/Distribution/Hypergeometric.hs b/src/Data/Random/Distribution/Hypergeometric.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Random/Distribution/Hypergeometric.hs
@@ -0,0 +1,56 @@
+{-# LANGUAGE Trustworthy #-}
+{-# LANGUAGE
+    MultiParamTypeClasses,
+    FlexibleContexts,
+    FlexibleInstances
+  #-}
+-- |
+-- Module    : Statistics.Distribution.Hypergeometric.GenVar
+-- Copyright : (c) 2015 Sam Rijs,
+--             (c) 2005 Robert Kern,
+--             (c) 1998 Ivan Frohne
+-- License   : MIT
+--
+-- Maintainer  : srijs@airpost.net
+-- Stability   : experimental
+--
+-- The parameters of the distribution describe /k/ elements chosen
+-- from a population of /l/, with /m/ elements of one type, and
+-- /l/-/m/ of the other (all are positive integers).
+
+module Data.Random.Distribution.Hypergeometric
+  ( Hypergeometric
+  -- ** Constructors
+  , hypergeometric
+  -- ** Accessors
+  , getM, getL, getK
+  -- ** Variate Generation
+  , hypergeometricVar
+  , hypergeometricVarT
+  ) where
+
+import Data.Random.RVar
+import Data.Random.Distribution
+import Data.Random.Distribution.Uniform
+
+import Data.Random.Distribution.Hypergeometric.Impl
+
+data Hypergeometric t = Hypergeometric { getK :: !t, getL :: !t,  getM :: !t }
+
+-- | Constructs a hypergeometric distribution from the parameters /k/, /l/ and /m/.
+--   Fails if /l/ is negative, /k/ is not in [0,/l/] or /m/ is not in [0,/l/].
+hypergeometric :: (Num a, Ord a) => a -> a -> a -> Hypergeometric a
+hypergeometric k l m 
+  | l < 0 = error "l must not be negative"
+  | m < 0 || m > l = error "m must be in [0,l]"
+  | k < 0 || k > l = error "k must be in [0,l]"
+  | otherwise = Hypergeometric k l m
+
+hypergeometricVar :: (Num a, Ord a, Distribution Hypergeometric a) => a -> a -> a -> RVar a
+hypergeometricVar = hypergeometricVarT
+
+hypergeometricVarT :: (Num a, Ord a, Distribution Hypergeometric a) => a -> a -> a -> RVarT m a
+hypergeometricVarT k l m = rvarT (hypergeometric k l m)
+
+instance (Integral t) => Distribution Hypergeometric t where
+  rvarT (Hypergeometric k l m) = rhyper (k, l, m)
diff --git a/src/Data/Random/Distribution/Hypergeometric/Impl.hs b/src/Data/Random/Distribution/Hypergeometric/Impl.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Random/Distribution/Hypergeometric/Impl.hs
@@ -0,0 +1,43 @@
+module Data.Random.Distribution.Hypergeometric.Impl where
+
+import Data.Random.RVar
+import Data.Random.Distribution
+import Data.Random.Distribution.Uniform
+
+import Numeric.SpecFunctions (logGamma)
+
+d1 = 1.7155277699214135 -- 2*sqrt(2/e)
+d2 = 0.8989161620588988 -- 3 - 2*sqrt(3/e)
+
+rhyper :: (Integral a) => (a, a, a) -> RVarT m a
+rhyper (sample, popsize, good) = return . fix2 . fix1 =<< loop
+  where fix1 z = if good > bad then m - z else z
+        fix2 z = if m < sample then good - z else z
+        mingoodbad = min good bad
+        bad = popsize - good
+        maxgoodbad = max good bad
+        m = min sample (popsize - sample)
+        gamma z = sum $ map (logGamma . fromIntegral)
+          [ z + 1,     mingoodbad - z + 1
+          , m - z + 1, maxgoodbad - m + z + 1 ]
+        d4 = fromIntegral mingoodbad / fromIntegral popsize
+        d5 = 1 - d4
+        d6 = fromIntegral m * d4 + 0.5
+        d7 = sqrt $ fromIntegral (popsize - m) * fromIntegral sample * d4 * d5 / fromIntegral (popsize - 1) + 0.5
+        d8 = d1 * d7 + d2
+        d9 = floor $ fromIntegral (m + 1) * fromIntegral (mingoodbad + 1) / fromIntegral (popsize + 2)
+        d10 = gamma d9
+        d11 = fromIntegral $ min (min m mingoodbad + 1) (floor (d6 + 16 * d7))
+        -- 16 for 16-decimal-digit precision in d1 and d2
+        loop = do
+          x <- doubleUniform 0 1
+          y <- doubleUniform 0 1
+          case () of 
+            _  | w < 0 || w >= d11    -> loop -- fast rejection
+               | x * (4 - x) - 3 <= t -> return z -- fast acceptance
+               | x * (x - t) >= 1     -> loop -- fast rejection
+               | 2 * (log x) <= t     -> return z -- acceptance
+               | otherwise            -> loop -- rejection
+               where w = d6 + d8 * (y - 0.5) / x
+                     z = floor w
+                     t = d10 - gamma z
diff --git a/src/Data/Random/Distribution/Hypergeometric/Test.hs b/src/Data/Random/Distribution/Hypergeometric/Test.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Random/Distribution/Hypergeometric/Test.hs
@@ -0,0 +1,59 @@
+module Data.Random.Distribution.Hypergeometric.Test where
+
+import Data.Int
+
+import Data.Random
+import Data.Random.Sample (sampleFrom)
+import Data.Random.Distribution.Hypergeometric
+
+import System.Random.MWC
+
+import Data.Vector (fromList)
+
+import Test.QuickCheck
+import Test.QuickCheck.Monadic
+
+import Distribution.TestSuite.QuickCheck
+
+instance Arbitrary Seed where
+  arbitrary = return . toSeed . fromList =<< vector 258
+
+testArbitraryRandom :: (GenIO -> IO Bool) -> Seed -> Property
+testArbitraryRandom f s = monadicIO $ assert =<< run (f =<< restore s)
+
+tests :: IO [Test]
+tests = return
+
+  [ testGroup "identities"
+
+    [ testGroup "small"
+
+      [ testProperty "draw nil" $ \p -> testArbitraryRandom $ \g -> do
+        let i = (getSmall . getPositive) p :: Int64
+        v <- sampleFrom g $ hypergeometric i i 0
+        return $ v == 0
+
+      , testProperty "draw all" $ \p -> testArbitraryRandom $ \g -> do
+        let i = (getSmall . getPositive) p :: Int64
+        v <- sampleFrom g $ hypergeometric i i i
+        return $ v == i
+
+      ]
+
+    , testGroup "large"
+
+      [ testProperty "draw nil" $ \p -> testArbitraryRandom $ \g -> do
+        let i = (getLarge . getPositive) p :: Int64
+        v <- sampleFrom g $ hypergeometric i i 0
+        return $ v == 0
+
+      , testProperty "draw all" $ \p -> testArbitraryRandom $ \g -> do
+        let i = (getLarge . getPositive) p :: Int64
+        v <- sampleFrom g $ hypergeometric i i i
+        return $ v == i
+
+      ]
+
+    ]
+
+  ]
