diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for circular-enum
+
+## 0.1.0.0 -- 2023-05-31
+
+* 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) 2023 Mirko Westermeier
+
+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/circular-enum.cabal b/circular-enum.cabal
new file mode 100644
--- /dev/null
+++ b/circular-enum.cabal
@@ -0,0 +1,39 @@
+cabal-version:    3.0
+name:             circular-enum
+version:          0.1.0.0
+synopsis:         Make bounded enum types circular
+description:      Circular successor & predecessor for bounded enum types
+homepage:         https://github.com/memowe/circular-enum
+bug-reports:      https://github.com/memowe/circular-enum/issues
+license:          MIT
+license-file:     LICENSE
+author:           Mirko Westermeier
+maintainer:       mirko@westermeier.de
+copyright:        (c) 2023 Mirko Westermeier
+category:         Data
+build-type:       Simple
+extra-doc-files:  CHANGELOG.md
+source-repository head
+    type:       git
+    branch:     main
+    location:   git://github.com/memowe/circular-enum.git
+
+common warnings
+    ghc-options: -Wall
+
+library
+    import:           warnings
+    exposed-modules:  Data.Enum.Circular
+    build-depends:    base >=4.14.0.0 && < 5
+    hs-source-dirs:   src
+    default-language: Haskell2010
+
+test-suite circular-enum-test
+    import:           warnings
+    default-language: Haskell2010
+    type:             exitcode-stdio-1.0
+    hs-source-dirs:   test
+    main-is:          Main.hs
+    build-depends:    base >=4.14.0.0
+                    , circular-enum
+                    , hspec >= 2.10 && < 3
diff --git a/src/Data/Enum/Circular.hs b/src/Data/Enum/Circular.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Enum/Circular.hs
@@ -0,0 +1,35 @@
+{-|
+Module      : Data.Enum.Circular
+Description : Circular successor & predecessor for bounded enum types
+Copyright   : (c) 2023 Mirko Westermeier
+License     : MIT
+
+Sometimes, bounded enum types should be circular. Consider this enum
+type of directions:
+
+@
+data Direction  = North
+                | East
+                | South
+                | West
+                deriving (Eq, Enum, Bounded)
+@
+
+The 'Enum' instance allows for @succ North@ to be @East@ and @succ East@
+to be @South@. But in this case, one would like to have some kind of
+@succ@ with @succ West = North@ again. With 'Eq' and 'Bounded' instances,
+the functions defined in this module act like circular versions of 'succ'
+and 'pred'.
+-}
+
+module Data.Enum.Circular (csucc, cpred) where
+
+-- | Circular version of 'succ'
+csucc :: (Eq a, Enum a, Bounded a) => a -> a
+csucc x | x == maxBound = minBound
+        | otherwise     = succ x
+
+-- | Circular version of 'pred'
+cpred :: (Eq a, Enum a, Bounded a) => a -> a
+cpred x | x == minBound = maxBound
+        | otherwise     = pred x
diff --git a/test/Main.hs b/test/Main.hs
new file mode 100644
--- /dev/null
+++ b/test/Main.hs
@@ -0,0 +1,26 @@
+module Main (main) where
+
+import Data.Enum.Circular
+import Data.Function
+import Test.Hspec
+
+data Direction = N | E | S | W deriving (Show, Eq, Enum, Bounded)
+
+circularDirections :: Spec
+circularDirections = describe "Circular directions" $ do
+
+  describe "Boundaries" $ do
+    it "North after West"   $ csucc W `shouldBe` N
+    it "West before North"  $ cpred N `shouldBe` W
+
+  describe "Compatible with Enum instance" $ do
+    it "Successors" $
+      iterate csucc minBound `startShouldBe` cycle allDirs
+    it "Predecessors" $
+      iterate cpred maxBound `startShouldBe` cycle (reverse allDirs)
+
+  where allDirs         = enumFrom minBound :: [Direction]
+        startShouldBe   = shouldBe `on` take (length allDirs * 2)
+
+main :: IO ()
+main = hspec circularDirections
