diff --git a/aop-prelude.cabal b/aop-prelude.cabal
--- a/aop-prelude.cabal
+++ b/aop-prelude.cabal
@@ -4,7 +4,7 @@
 -- http://haskell.org/cabal/users-guide/
 
 name:                aop-prelude
-version:             0.4.1.2
+version:             0.5.0.0
 synopsis:            prelude for Algebra of Programming
 description:         prelude for Algenra of Programming, the original code was created by Richard Bird.
 homepage:            https://github.com/cutsea110/aop-prelude.git
@@ -19,6 +19,7 @@
 
 library
   exposed-modules:     AOPPrelude
+                     , Combinatorial
   -- other-modules:
   other-extensions:    NoImplicitPrelude
   build-depends:       base >=4.12.0.0 && <4.19, ghc-prim >=0.5.3, integer-gmp
diff --git a/src/Combinatorial.hs b/src/Combinatorial.hs
new file mode 100644
--- /dev/null
+++ b/src/Combinatorial.hs
@@ -0,0 +1,65 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+module Combinatorial
+  ( subseqs
+  , partitions
+  , perms
+  , consl, consr
+  , cup
+  , interleave
+  ) where
+
+import AOPPrelude
+import Data.List ((\\))
+
+subseqs :: [a] -> [[a]]
+subseqs = catalist (e, f)
+  where
+    e = wrap []
+    f = cat . pair (list cons . cpr, outr)
+
+new :: (a, [[a]]) -> [[a]]
+new = cons . cross (wrap, id)
+
+glues :: (a, [[a]]) -> [[[a]]]
+glues (a, [])   = []
+glues (a, x:xs) = [(a:x):xs]
+
+partitions :: [a] -> [[[a]]]
+partitions = catalist (e, f)
+  where
+    e = wrap []
+    f = concat . list (cons . pair (new, glues)) . cpr
+
+adds :: (a, [a]) -> [[a]]
+adds (a, x) = [y ++ [a] ++ z | (y, z) <- splits x]
+
+perms :: [a] -> [[a]]
+perms = catalist (e, f)
+  where
+    e = wrap []
+    f = concat . list adds . cpr
+
+consl :: (a, ([a], b)) -> ([a], b)
+consl (a, (x, y)) = (a:x, y)
+
+consr :: (a, (b, [a])) -> (b, [a])
+consr (a, (x, y)) = (x, a:y)
+
+cup :: ([a], [a]) -> [a]
+cup = uncurry (++)
+
+interleave :: [a] -> [([a], [a])]
+interleave = catalist (e, f)
+  where
+    e = wrap nilp
+    f = cup . pair (list consl, list consr) . cpr
+    nilp = ([], [])
+
+isEqual :: Eq a => [a] -> [a] -> Bool
+xs `isEqual` ys = null (xs \\ ys) && null (ys \\ xs)
+
+elem :: Eq a => [a] -> [[a]] -> Bool
+elem x = catalist (e, f)
+  where
+    e = False
+    f (y, b) = b || y `isEqual` x
