diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,2 @@
+# 0.1
+* Initial commit
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2015, The University of Kansas
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * 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.
+
+    * Neither the name of The University of Kansas nor the names of other
+      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
+OWNER 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,3 @@
+# natural-transformation [![Hackage version](https://img.shields.io/hackage/v/natural-transformation.svg?style=flat)](http://hackage.haskell.org/package/natural-transformation) [![Build Status](https://img.shields.io/travis/ku-fpg/natural-transformation.svg?style=flat)](https://travis-ci.org/ku-fpg/natural-transformation)
+
+A natural transformation transforms a container `f a` into another container `g a` while preserving the internal structure. Natural transformations act as functor morphisms in category theory. Technically, `f` and `g` should be functors, but we allow any correctly-shaped structure.
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/natural-transformation.cabal b/natural-transformation.cabal
new file mode 100644
--- /dev/null
+++ b/natural-transformation.cabal
@@ -0,0 +1,43 @@
+name:                natural-transformation
+version:             0.1
+synopsis:            A natural transformation package.
+description:         A natural transformation transforms a container @f a@ into another
+                     container @g a@ while preserving the internal structure. Natural
+                     transformations act as functor morphisms in category theory.
+homepage:            https://github.com/ku-fpg/natural-transformation
+bug-reports:         https://github.com/ku-fpg/natural-transformation/issues
+license:             BSD3
+license-file:        LICENSE
+stability:           Provisional
+author:              Andy Gill
+maintainer:          Andy Gill <andygill@ku.edu>
+copyright:           Copyright (c) 2015 The University of Kansas
+category:            Control
+build-type:          Simple
+extra-source-files:  CHANGELOG.md, README.md
+cabal-version:       >= 1.10
+
+source-repository head
+  type:                git
+  location:            git://github.com/ku-fpg/natural-transformation
+
+library
+  exposed-modules:     Control.Natural
+                       Control.Transformation
+  build-depends:       base >= 3 && < 5
+  hs-source-dirs:      src
+  default-language:    Haskell2010
+  ghc-options:         -Wall
+
+test-suite natural-transformation-properties
+  type:                exitcode-stdio-1.0
+  main-is:             Properties.hs
+  build-depends:       base                   >= 4.5 && < 5
+                     , containers             >= 0.1 && < 0.6
+                     , natural-transformation == 0.1
+                     , quickcheck-instances   >= 0.1 && < 0.4
+                     , tasty                  >= 0.8 && < 0.11
+                     , tasty-quickcheck       >= 0.8 && < 0.9
+  hs-source-dirs:      tests
+  default-language:    Haskell2010
+  ghc-options:         -Wall
diff --git a/src/Control/Natural.hs b/src/Control/Natural.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Natural.hs
@@ -0,0 +1,73 @@
+{-# LANGUAGE CPP, FlexibleInstances, RankNTypes, TypeFamilies, TypeOperators #-}
+
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 706 && MIN_VERSION_base(4,7,0)
+# define LANGUAGE_PolyKinds
+{-# LANGUAGE PolyKinds #-}
+#endif
+
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 708
+# define LANGUAGE_DeriveDataTypeable
+{-# LANGUAGE DeriveDataTypeable #-}
+#else
+{-# LANGUAGE ScopedTypeVariables #-}
+#endif
+
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
+# if defined(LANGUAGE_DeriveDataTypeable)
+{-# LANGUAGE Safe #-}
+# else
+{-# LANGUAGE Trustworthy #-}
+# endif
+#endif
+
+{-|
+Module:      Control.Natural
+Copyright:   (C) 2015 The University of Kansas
+License:     BSD-style (see the file LICENSE)
+Maintainer:  Andy Gill
+Stability:   Experimental
+
+A data type for natural transformations.
+-}
+module Control.Natural ((:~>)(..)) where
+
+#if defined(LANGUAGE_PolyKinds)
+import qualified Control.Category as C (Category(..))
+#endif
+
+#if !(MIN_VERSION_base(4,8,0))
+import           Data.Monoid (Monoid(..))
+#endif
+import           Data.Typeable
+
+---------------------------------------------------------------------------
+-- Code adapted, with permission, from Edward Kmett's @indexed@ package.
+---------------------------------------------------------------------------
+
+infixr 0 :~>, $$
+-- | A natural transformation from @f@ to @g@.
+newtype f :~> g = Nat { ($$) :: forall x. f x -> g x }
+#if defined(LANGUAGE_DeriveDataTypeable)
+  deriving Typeable
+#else
+instance (Typeable1 f, Typeable1 g) => Typeable (f :~> g) where
+    typeOf _ = mkTyConApp natTyCon [typeOf1 (undefined :: f a), typeOf1 (undefined :: g a)]
+
+natTyCon :: TyCon
+# if MIN_VERSION_base(4,4,0)
+natTyCon = mkTyCon3 "natural-transformation" "Control.Natural" ":~>"
+# else
+natTyCon = mkTyCon ":~>"
+# endif
+{-# NOINLINE natTyCon #-}
+#endif
+
+#if defined(LANGUAGE_PolyKinds)
+instance C.Category (:~>) where
+    id = Nat id
+    Nat f . Nat g = Nat (f . g)
+#endif
+
+instance f ~ g => Monoid (f :~> g) where
+    mempty = Nat id
+    mappend (Nat f) (Nat g) = Nat (f . g)
diff --git a/src/Control/Transformation.hs b/src/Control/Transformation.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Transformation.hs
@@ -0,0 +1,37 @@
+{-# LANGUAGE CPP, FlexibleInstances, FunctionalDependencies,
+             MultiParamTypeClasses, TypeOperators #-}
+
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 706 && MIN_VERSION_base(4,7,0)
+{-# LANGUAGE PolyKinds #-}
+#endif
+
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
+{-# LANGUAGE Safe #-}
+#endif
+
+{-|
+Module:      Control.Transformation
+Copyright:   (C) 2015 The University of Kansas
+License:     BSD-style (see the file LICENSE)
+Maintainer:  Andy Gill
+Stability:   Experimental
+
+A type class for transformations.
+-}
+module Control.Transformation (Transformation(..)) where
+
+import Control.Natural ((:~>)(..))
+
+infixr 0 #
+-- | A (natural) transformation is inside @t@, and contains @f@ and @g@
+-- (typically 'Functor's).
+-- 
+-- The order of arguments allows the use of @GeneralizedNewtypeDeriving@ to wrap
+-- a 'Natural', but maintain the 'Transformation' constraint. Thus, '#' can be used
+-- on abstract data types.
+class Transformation f g t | t -> f g where
+    -- | The invocation method for a natural transformation.
+    (#) :: t -> f a -> g a
+
+instance Transformation f g (f :~> g) where
+    Nat f # g = f g
diff --git a/tests/Properties.hs b/tests/Properties.hs
new file mode 100644
--- /dev/null
+++ b/tests/Properties.hs
@@ -0,0 +1,76 @@
+{-# LANGUAGE CPP, TypeOperators #-}
+{-|
+Module:      Main
+Copyright:   (C) 2015 The University of Kansas
+License:     BSD-style (see the file LICENSE)
+Maintainer:  Andy Gill
+Stability:   Experimental
+
+@QuickCheck@ properties for natural transformations.
+-}
+module Main (main) where
+
+import Control.Natural ((:~>)(..))
+import Control.Transformation (Transformation(..))
+
+import Data.Foldable (toList)
+#if !(MIN_VERSION_base(4,8,0))
+import Data.Monoid (Monoid(..))
+#endif
+import Data.Sequence (Seq, fromList)
+
+import Test.QuickCheck.Instances ()
+import Test.Tasty (TestTree, defaultMain, testGroup)
+import Test.Tasty.QuickCheck (testProperty)
+
+main :: IO ()
+main = defaultMain testProperties
+
+testProperties :: TestTree
+testProperties = testGroup "QuickCheck properties"
+    [ testProperty "Free theorem ([] :~> Seq)" (prop_freeTheorem (+1)    listSeqNT :: [Int] -> Bool)
+    , testProperty "Free theorem (Seq :~> [])" (prop_freeTheorem reverse seqListNT :: Seq String -> Bool)
+    , testProperty "Monoid laws"               (prop_monoidLaws listShiftNT listReverseNT listShiftNT :: [Int] -> Bool)
+    ]
+
+-- | Verifies the free theorem for natural transformations, i.e., that
+-- 
+-- @
+-- fmap h . r == r . fmap h
+-- @
+prop_freeTheorem :: (Eq (g b), Functor f, Functor g, Transformation f g t)
+                 => (a -> b) -> t -> f a -> Bool
+prop_freeTheorem h r t = fmap h (r # t) == (r # fmap h t)
+
+-- | Verifies that natural transformations form a law-abiding 'Monoid', i.e., that
+-- 
+--  * @mappend mempty x = x@
+--
+--  * @mappend x mempty = x@
+--
+--  * @mappend x (mappend y z) = mappend (mappend x y) z@
+prop_monoidLaws :: (Eq (f a), Monoid t, Transformation f f t)
+                => t -> t -> t -> f a -> Bool
+prop_monoidLaws x y z t = (mappend mempty x # t) == (x # t)
+                       && (mappend x mempty # t) == (x # t)
+                       && (mappend x (mappend y z) # t)
+                          == (mappend (mappend x y) z # t)
+
+-- | A natural transformations from lists to lists that 'reverse's.
+listReverseNT :: [] :~> []
+listReverseNT = Nat reverse
+
+-- | A natural transformation from lists to lists that shifts all elements to the left,
+-- moving the head element to the back.
+listShiftNT :: [] :~> []
+listShiftNT = Nat $ \l -> case l of
+                               []     -> []
+                               (x:xs) -> xs ++ [x]
+
+-- | A natural transformation from lists to 'Seq's.
+listSeqNT :: [] :~> Seq
+listSeqNT = Nat fromList
+
+-- | A natural transformation from 'Seq's to lists.
+seqListNT :: Seq :~> []
+seqListNT = Nat toList
