diff --git a/Data/Nat.hs b/Data/Nat.hs
new file mode 100644
--- /dev/null
+++ b/Data/Nat.hs
@@ -0,0 +1,121 @@
+{-# LANGUAGE CPP #-}
+
+#ifdef HAVE_TYPEABLE
+{-# LANGUAGE DeriveDataTypeable #-}
+#endif
+
+#ifdef HAVE_GENERIC
+{-# LANGUAGE DeriveGeneric #-}
+#endif
+
+{-# OPTIONS_GHC -fno-warn-unused-matches -fno-warn-name-shadowing #-}
+
+-- | Module:      Data.Nat
+--   License:     BSD3
+--   Copyright:   2012 Gábor Lehel
+--   Stability:   experimental
+--   Maintainer:  Gábor Lehel <illissius@gmail.com>
+--   Portability: portable
+--
+-- Operations which are undefined mathematically (@0 / 0@, @infinity * 0@, @infinity - infinity@, etc.)
+-- also have undefined results in this implementation.
+
+module Data.Nat (Nat(..), nat, foldNat, unfoldNat, infinity, diff) where
+
+import Control.Arrow            (first)
+import Data.Ix                  (Ix(..))
+import Numeric.Natural.Internal (Whole(..))
+
+#ifdef HAVE_TYPEABLE
+import Data.Typeable            (Typeable)
+#define MAYBE_TYPEABLE , Typeable
+#else
+#define MAYBE_TYPEABLE
+#endif
+
+#ifdef HAVE_GENERIC
+import GHC.Generics             (Generic)
+#define MAYBE_GENERIC  , Generic
+#else
+#define MAYBE_GENERIC
+#endif
+
+data Nat = Zero | Succ Nat
+           deriving (Eq, Ord, Read, Show MAYBE_TYPEABLE MAYBE_GENERIC)
+
+negative :: String -> a
+negative f = error ("Data.Nat." ++ f ++ ": would be negative")
+
+instance Enum Nat where
+    succ                   = Succ
+    pred                   = nat (negative "pred") id
+    toEnum                 = fromInteger  . fromIntegral
+    fromEnum               = fromIntegral . toInteger
+    enumFrom               = iterate succ
+    enumFromTo     f    to = enumFromThenTo f (succ f) to
+    enumFromThen   f th    = enumFromThenTo f th (if f < th then maxBound else minBound)
+    enumFromThenTo f th to = either (const []) (accum f) (diff to f `divD` diff_th_f) where
+        accum n            = nat [n] ((n:) . accum (step n))
+        step               = either subtract (+) diff_th_f
+        diff_th_f          = diff th f
+        divD               = either (\x -> either (Right                            . div x) (Left  . div x))
+                                    (\x -> either ((if x == 0 then Right else Left) . div x) (Right . div x))
+                                    -- maybe this could be done simpler?
+
+instance Bounded Nat where
+    minBound = 0
+    maxBound = infinity -- is this polite?
+
+instance Num Nat where
+    (+) n       = foldNat n succ
+    (*) n       = foldNat 0 (+n)
+    (-) n       = nat n ((-) $! nat (negative "-") id n)
+    negate      = nat 0 (const $ negative "negate")
+    abs         = id
+    signum      = nat 0 (const 1)
+    fromInteger = unfoldNat $ \n -> case n of n | n < 0     -> negative "fromInteger"
+                                                | n > 0     -> Just (n - 1)
+                                                | otherwise -> Nothing
+
+instance Real Nat where
+    toRational = toRational . toNatural
+
+instance Integral Nat where
+    quotRem n m = either (const (0, n)) (\x -> first succ (quotRem x m)) (diff n m)
+    divMod      = quotRem
+    toInteger   = toInteger . toNatural
+
+instance Whole Nat where
+    toNatural  = foldNat 0 succ
+    unsafePred = pred
+
+instance Ix Nat where
+    range     (n, m)   = [n..m]
+    index     (n, m) i = fromIntegral (n - i)
+    inRange   (n, m) i = n <= i && i <= m
+    rangeSize (n, m)   = fromIntegral (m - n)
+
+-- | Shallow deconstruction. Returns the first argument if @Zero@, applies the second argument to the inner value if @Succ@.
+nat :: r -> (Nat -> r) -> Nat -> r
+nat z s Zero     = z
+nat z s (Succ n) = s n
+
+-- | Returns the first argument if @Zero@, applies the second argument recursively for each @Succ@.
+foldNat :: r -> (r -> r) -> Nat -> r
+foldNat z s = nat z (s . foldNat z s)
+
+-- | Build a @Nat@ from a seed value: the first argument should return the next seed value
+--   if the building is to continue, or @Nothing@ if it is to stop.  A @Succ@ is added at each iteration.
+unfoldNat :: (a -> Maybe a) -> a -> Nat
+unfoldNat f a = maybe Zero (succ . unfoldNat f) (f a)
+
+-- | Very big!
+infinity :: Nat
+infinity = succ infinity
+
+-- | > diff n m | n >= m    = Right (n - m)
+--   >          | otherwise = Left  (m - n)
+diff :: Nat -> Nat -> Either Nat Nat
+diff (Succ n) (Succ m) = diff n m
+diff n        Zero     = Right n
+diff Zero     n        = Left  n
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright 2012 Gábor Lehel
+
+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 his contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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/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-nat.cabal b/data-nat.cabal
new file mode 100644
--- /dev/null
+++ b/data-nat.cabal
@@ -0,0 +1,47 @@
+name:          data-nat
+category:      Data, Math
+version:       0.1
+author:        Gábor Lehel
+maintainer:    Gábor Lehel <illissius@gmail.com>
+homepage:      http://github.com/glehel/data-nat
+copyright:     Copyright (C) 2012 Gábor Lehel
+license:       BSD3
+license-file:  LICENSE
+stability:     experimental
+cabal-version: >= 1.10
+build-type:    Simple
+synopsis:      data Nat = Zero | Succ Nat
+description:
+    The usual @data Nat = Zero | Succ Nat@ datatype with the appropriate instances.
+    .
+    Should be portable to any Haskell 98 compiler which supports the @CPP@ extension.
+
+source-repository head
+    type:      git
+    location:  git://github.com/glehel/data-nat.git
+
+library
+    default-language:
+        Haskell98
+
+    other-extensions:
+        CPP
+
+    exposed-modules:
+        Data.Nat
+
+    -- not sure how or if to constrain base...
+    build-depends:
+        base       >= 4   && < 5,
+        semigroups >= 0.7 && < 0.9
+
+    -- here either
+    if impl(ghc)
+        build-depends: ghc-prim == 0.2.*
+        cpp-options:   -DHAVE_TYPEABLE
+
+    if impl(ghc >= 7.2)
+        cpp-options: -DHAVE_GENERIC
+
+    ghc-options:
+        -Wall
