diff --git a/CHANGES.md b/CHANGES.md
new file mode 100644
--- /dev/null
+++ b/CHANGES.md
@@ -0,0 +1,7 @@
+`HUnit-approx` changelog
+========================
+
+Version 1.0
+-----------
+
+* Initial release: assertApproxEquals, and assertion and test combinators.
diff --git a/HUnit-approx.cabal b/HUnit-approx.cabal
new file mode 100644
--- /dev/null
+++ b/HUnit-approx.cabal
@@ -0,0 +1,41 @@
+name:           HUnit-approx
+version:        1.0
+cabal-version:  >= 1.10
+synopsis:       Approximate equality for floating point numbers with HUnit
+homepage:       https://github.com/goldfirere/HUnit-approx
+category:       Testing
+author:         Richard Eisenberg <eir@cis.upenn.edu>
+maintainer:     Richard Eisenberg <eir@cis.upenn.edu>
+bug-reports:    https://github.com/goldfirere/HUnit-approx/issues
+stability:      intended to be stable
+extra-source-files: README.md, CHANGES.md
+license:        BSD3
+license-file:   LICENSE
+build-type:     Simple
+description:
+    This package exports combinators useful in comparing floating-point numbers
+    in HUnit tests, by using approximate equality.
+
+source-repository this
+  type:     git
+  location: https://github.com/goldfirere/HUnit-approx.git
+  tag:      v1.0
+
+library
+  build-depends:      
+      base == 4.*
+    , HUnit >= 1.2
+  exposed-modules:    Test.HUnit.Approx
+  default-language:   Haskell2010
+
+test-suite sanity-check
+  type:               exitcode-stdio-1.0
+  ghc-options:        -Wall -Werror -main-is Tests.Main
+  default-language:   Haskell2010
+  main-is:            Tests/Main.hs
+
+  build-depends:
+      base == 4.*
+    , HUnit >= 1.2
+    , HUnit-approx
+      
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2014, Richard Eisenberg
+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 author 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,10 @@
+`HUnit-approx`
+==============
+
+[![Build Status](https://travis-ci.org/goldfirere/HUnit-approx.svg?branch=master)](https://travis-ci.org/goldfirere/HUnit-approx)
+
+This Haskell package provides operators to test approximate equality among
+numerical values, compatible with
+[HUnit](http://hackage.haskell.org/package/HUnit). It uses implicit variables
+to make for a clean interface, where approximate comparison looks like a
+binary operator.
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/Test/HUnit/Approx.hs b/Test/HUnit/Approx.hs
new file mode 100644
--- /dev/null
+++ b/Test/HUnit/Approx.hs
@@ -0,0 +1,85 @@
+{-# LANGUAGE ImplicitParams, CPP #-}
+#if __GLASGOW_HASKELL__ >= 707
+{-# LANGUAGE Safe #-}       -- Test.HUnit is not Safe in 7.6 and below
+#endif
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Test.HUnit.Approx
+-- Copyright   :  (C) 2014 Richard Eisenberg
+-- License     :  BSD-style (see LICENSE)
+-- Maintainer  :  Richard Eisenberg (eir@cis.upenn.edu)
+-- Stability   :  intended to be stable
+-- Portability :  not portable (uses implicit parameters)
+--
+-- This module exports combinators to allow approximate equality of
+-- floating-point values in HUnit tests.
+-----------------------------------------------------------------------------
+
+module Test.HUnit.Approx (
+  -- * Assertions
+  assertApproxEqual, (@~?), (@?~),
+
+  -- * Tests
+  (~~?), (~?~)
+  ) where
+
+import Test.HUnit
+import Control.Monad  ( unless )
+
+-- | Asserts that the specified actual value is approximately equal to the
+-- expected value. The output message will contain the prefix, the expected
+-- value, the actual value, and the maximum margin of error.
+--  
+-- If the prefix is the empty string (i.e., @\"\"@), then the prefix is omitted
+-- and only the expected and actual values are output.
+assertApproxEqual :: (Ord a, Num a, Show a)
+                  => String -- ^ The message prefix
+                  -> a      -- ^ Maximum allowable margin of error
+                  -> a      -- ^ The expected value 
+                  -> a      -- ^ The actual value
+                  -> Assertion
+assertApproxEqual preface epsilon expected actual =
+  unless (abs (actual - expected) <= epsilon) (assertFailure msg)
+  where msg = (if null preface then "" else preface ++ "\n") ++
+              "expected: " ++ show expected ++ "\n but got: " ++ show actual ++
+              "\n (maximum margin of error: " ++ show epsilon ++ ")"
+
+-- | Asserts that the specified actual value is approximately equal to the
+-- expected value (with the expected value on the right-hand side). The margin
+-- of error is specified with the implicit parameter @epsilon@.
+(@?~) :: (Ord a, Num a, Show a, ?epsilon :: a)
+      => a        -- ^ The actual value
+      -> a        -- ^ The expected value
+      -> Assertion
+x @?~ y = assertApproxEqual "" ?epsilon y x
+infix 1 @?~
+
+-- | Asserts that the specified actual value is approximately equal to the
+-- expected value (with the expected value on the left-hand side). The margin
+-- of error is specified with the implicit parameter @epsilon@.
+(@~?) :: (Ord a, Num a, Show a, ?epsilon :: a)
+      => a     -- ^ The expected value
+      -> a     -- ^ The actual value
+      -> Assertion
+x @~? y = assertApproxEqual "" ?epsilon x y
+infix 1 @~?
+
+-- | Shorthand for a test case that asserts approximate equality (with the
+-- expected value on the left-hand side, and the actual value on the
+-- right-hand side).
+(~~?) :: (Ord a, Num a, Show a, ?epsilon :: a)
+      => a     -- ^ The expected value
+      -> a     -- ^ The actual value
+      -> Test
+expected ~~? actual = TestCase (expected @~? actual)
+infix 1 ~~?
+
+-- | Shorthand for a test case that asserts approximate equality (with the
+-- actual value on the left-hand side, and the expected value on the
+-- right-hand side).
+(~?~) :: (Ord a, Num a, Show a, ?epsilon :: a)
+      => a     -- ^ The actual value
+      -> a     -- ^ The expected value 
+      -> Test
+actual ~?~ expected = TestCase (actual @?~ expected)
+infix 1 ~?~
diff --git a/Tests/Main.hs b/Tests/Main.hs
new file mode 100644
--- /dev/null
+++ b/Tests/Main.hs
@@ -0,0 +1,34 @@
+{- Tests for the HUnit-approx package
+
+   Copyright (c) 2014 Richard Eisenberg
+   eir@cis.upenn.edu
+
+-}
+
+{-# LANGUAGE ImplicitParams, ScopedTypeVariables #-}
+{-# OPTIONS_GHC -fno-warn-type-defaults #-}
+
+module Tests.Main where
+
+import Test.HUnit
+import Test.HUnit.Approx
+import Control.Monad
+import Control.Exception
+
+main :: IO ()
+main = void $ runTestTT tests
+
+assertNot :: Assertion -> Assertion
+assertNot asrt = do
+  result <- try asrt
+  case result of
+    Left (_ :: SomeException) -> return () -- success!
+    Right _                   -> assertFailure "Inverted assertion succeeded"
+
+tests :: Test
+tests =
+  let ?epsilon = 0.0001 in
+  TestList [ "refl" ~: 4.0 ~?~ 4.0
+           , "manual" ~: 4.0 ~~? 4.000000001
+           , "calc" ~: (0.1 + 0.1 + 0.1 @?~ 0.3)
+           , "not" ~: assertNot (4.005 @~? 4) ]
