diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for data-compat
+
+## 0.1.0.0 -- 2019-04-23
+
+* First version. Released on an unsuspecting world.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2019 Travis Whitaker
+
+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/data-compat.cabal b/data-compat.cabal
new file mode 100644
--- /dev/null
+++ b/data-compat.cabal
@@ -0,0 +1,23 @@
+cabal-version:       2.2
+name:                data-compat
+version:             0.1.0.0
+synopsis:            Define Backwards Compatibility Schemes for Arbitrary Data
+description:         Define Backwards Compatibility Schemes for Arbitrary Data
+homepage:            https://github.com/TravisWhitaker/data-compat
+bug-reports:         https://github.com/TravisWhitaker/data-compat/issues
+license:             MIT
+license-file:        LICENSE
+author:              Travis Whitaker
+maintainer:          pi.boy.travis@gmail.com
+copyright:           Travis Whitaker 2019
+category:            Data
+extra-source-files:  CHANGELOG.md
+
+library
+  exposed-modules:     Data.Compat
+  -- other-modules:
+  -- other-extensions:
+  build-depends:       base ^>=4.12.0.0
+                     , constraints ^>= 0.10
+  hs-source-dirs:      src
+  default-language:    Haskell2010
diff --git a/src/Data/Compat.hs b/src/Data/Compat.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Compat.hs
@@ -0,0 +1,68 @@
+{-|
+Module      : Data.Compat
+Description : Backwards Compatibility Schemes for Arbitrary Data
+Copyright   : Travis Whitaker 2019
+License     : MIT
+Maintainer  : pi.boy.travis@gmail.com
+Stability   : Provisional
+Portability : Portable
+
+See <http://programmable.computer/compatible.html> for a full exposition and
+worked examples.
+-}
+
+{-# LANGUAGE ConstraintKinds
+           , FlexibleContexts
+           , KindSignatures
+           , RankNTypes
+           , ScopedTypeVariables
+           , TypeFamilies
+           , TypeApplications
+           #-}
+
+module Data.Compat where
+
+import Control.Applicative
+
+import Data.Constraint
+
+import Data.Proxy
+
+-- | A class for backwards-compatible data.
+class Compat a where
+    -- | The predecessor for this type, i.e. the type for the data schema
+    --   directly preceeding 'a'.
+    type Pred a             :: *
+    -- | Any additional constraints required to yield data values. Typically
+    --   this will be a class that provides a parser.
+    type CompatConstraint a :: * -> Constraint
+    -- | A type for wrapping migration results. It is most useful if this type
+    --   has `Alternative` and `Monad` instances, enabling the use of
+    --   `getCompatible`. `Maybe` is a good first choice.
+    type CompatF a          :: * -> *
+    -- | How to migrate from a value of the preceeding schema to the current
+    --   schema.
+    migrate  :: Pred a -> (CompatF a) a
+    continue :: Proxy a
+             -> Maybe (Dict ( Compat (Pred a)
+                            , (CompatConstraint a) (Pred a)
+                            , CompatConstraint a ~ CompatConstraint (Pred a)
+                            , CompatF a ~ CompatF (Pred a)
+                            )
+                      )
+
+-- | Recursively migrate a data value to the most recent schema, if possible.
+getCompatible
+    :: forall a.
+       ( Compat a
+       , (CompatConstraint a) a
+       , Alternative (CompatF a)
+       , Monad (CompatF a)
+       )
+    => (forall c. (Compat c, (CompatConstraint a) c) => (CompatF a) c)
+    -> (CompatF a) a
+getCompatible f =
+    let f' = case continue (Proxy :: Proxy a) of
+                Nothing   -> empty
+                Just Dict -> getCompatible f >>= migrate
+    in f <|> f'
