diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,11 @@
+# Changelog for `typelevel-tools`
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to the
+[Haskell Package Versioning Policy](https://pvp.haskell.org/).
+
+## Unreleased
+
+## 0.1.0.0 - YYYY-MM-DD
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Yoshikuni Jujo (c) 2023
+
+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 Yoshikuni Jujo 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 @@
+# typelevel-tools
+
+type level tools
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/src/Data/TypeLevel/Bool.hs b/src/Data/TypeLevel/Bool.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypeLevel/Bool.hs
@@ -0,0 +1,10 @@
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE PolyKinds, ConstraintKinds #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Data.TypeLevel.Bool (b) where
+
+b :: forall {k} c (f :: k) (t :: k) tp b . (c (tp f), c (tp t)) =>
+	tp f -> tp t -> Bool -> (forall (a :: k) . c (tp a) => tp a -> b) -> b
+b f _ False fn  = fn f
+b _ t True fn = fn t
diff --git a/src/Data/TypeLevel/List.hs b/src/Data/TypeLevel/List.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypeLevel/List.hs
@@ -0,0 +1,34 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE ScopedTypeVariables, TypeApplications #-}
+{-# LANGUAGE TypeFamilies, TypeFamilyDependencies #-}
+{-# LANGUAGE DataKinds, PolyKinds #-}
+{-# LANGUAGE KindSignatures, TypeOperators #-}
+{-# LANGUAGE MultiParamTypeClasses, AllowAmbiguousTypes #-}
+{-# LANGUAGE FlexibleContexts, FlexibleInstances, UndecidableInstances #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Data.TypeLevel.List (
+	Length(..), IsPrefixOf, InfixIndex(..),
+	module Data.TypeLevel.List.Unzip
+	) where
+
+import Prelude hiding (length, unzip)
+
+import Data.TypeLevel.List.Unzip
+
+class Length (as :: [k]) where length :: Integral n => n
+instance Length '[] where length = 0
+instance Length as => Length (a ': as) where length = length @_ @as + 1
+
+class (xs :: [k]) `IsPrefixOf` (ys :: [k])
+instance '[] `IsPrefixOf` ys
+instance xs `IsPrefixOf` ys => (x ': xs) `IsPrefixOf` (x ': ys)
+
+class InfixIndex (xs :: [k]) (ys :: [k]) where infixIndex :: Int
+
+instance (x ': xs) `IsPrefixOf` (x ': ys) =>
+	InfixIndex (x ': xs) (x ': ys) where
+	infixIndex = 0
+
+instance {-# OVERLAPPABLE #-} InfixIndex xs ys => InfixIndex xs (y ': ys) where
+	infixIndex = infixIndex @_ @xs @ys + 1
diff --git a/src/Data/TypeLevel/List/Push.hs b/src/Data/TypeLevel/List/Push.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypeLevel/List/Push.hs
@@ -0,0 +1,10 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE DataKinds, PolyKinds #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Data.TypeLevel.List.Push where
+
+import Data.TypeLevel.List.TH
+
+push `mapM` [2 .. 62]
diff --git a/src/Data/TypeLevel/List/TH.hs b/src/Data/TypeLevel/List/TH.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypeLevel/List/TH.hs
@@ -0,0 +1,101 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE DataKinds, PolyKinds #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE TypeOperators #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Data.TypeLevel.List.TH where
+
+import Prelude hiding (unzip)
+import Language.Haskell.TH
+
+unzip :: Int -> DecQ
+unzip n = do
+	xys <- newName $ concat abc ++ "s"
+	xs <- newName `mapM` abc
+	ks <- newName `mapM` (("k" ++) <$> abc)
+	unzipGen (mkName $ "Unzip" ++ show n) (mkName $ "Push" ++ show n) xys xs ks
+	where
+	abc = take n varNames
+
+unzipGen :: Name -> Name -> Name -> [Name] -> [Name] -> DecQ
+unzipGen uz psh xys xs ks = do
+	t <- (listT `appT`) . tupleFromList $ varT <$> ks
+	closedTypeFamilyD uz [kindedTV xys t]
+		noSig Nothing
+		[tySynEqn Nothing lft0 rgt0, tySynEqn Nothing lft1 rgt1]
+	where
+	lft0 = conT uz `appT` promotedNilT
+	rgt0 = promotedTupleFromList $ (const promotedNilT) <$> xs
+	lft1 = appT (conT uz)
+		$ promotedTupleFromList (varT <$> xs) `promotedCons` varT xys
+	rgt1 = foldl appT (conT psh) (varT <$> xs) `appT` (conT uz `appT` varT xys)
+
+push :: Int -> DecQ
+push n = do
+	xys <- newName $ concat abc ++ "s"
+	xs <- newName `mapM` abc
+	ks <- newName `mapM` (("k" ++) <$> abc)
+	xss <- newName `mapM` ((++ "s") <$> abc)
+	pushGen (mkName $ "Push" ++ show n) xys xs ks xss
+	where
+	abc = take n varNames
+
+pushGen :: Name -> Name -> [Name] -> [Name] -> [Name] -> DecQ
+pushGen psh xys xs ks xss = closedTypeFamilyD psh
+	(zipWith kindedTV xs (varK <$> ks) ++ [plainTV xys]) NoSig Nothing [tySynEqn Nothing lft rgt ]
+	where
+	lft = foldl appT (conT psh) (varT <$> xs)
+		`appT` promotedTupleFromList (varT <$> xss)
+	rgt = promotedTupleFromList $ zipWith promotedCons (varT <$> xs) (varT <$> xss)
+
+tupleFromList :: Quote m => [m Type] -> m Type
+tupleFromList ts = foldl appT (tupleT $ length ts) ts
+
+promotedTupleFromList :: Quote m => [m Type] -> m Type
+promotedTupleFromList ts = foldl appT (promotedTupleT $ length ts) ts
+
+promotedCons :: Quote m => m Type -> m Type -> m Type
+promotedCons x y = promotedConsT `appT` x `appT` y
+
+varNames :: [String]
+varNames = ((: []) <$> ['a' .. 'z']) ++ [ cs ++ [c] | cs <- varNames, c <- ['a' .. 'z'] ]
+
+kindNames :: [String]
+kindNames = ('k' :) . show <$> [0 :: Int ..]
+
+mkZip :: Int -> DecQ
+mkZip n = do
+	xys <- newName `mapM` take n varNames
+	nus <- newName `mapM` take n (('_' :) <$> varNames)
+	xsys <- newName `mapM` take n ((++ "s") <$> varNames)
+	ks <- newName `mapM` take n kindNames
+	mkBar (mkName $ "Zip" ++ show n) xys nus xsys ks
+
+bar :: DecQ
+bar = mkBar (mkName "Zip2") [mkName "x", mkName "y"] [mkName "_x", mkName "_y"] [mkName "xs", mkName "ys"] [mkName "k0", mkName "k1"]
+
+mkBar :: Name -> [Name] -> [Name] -> [Name] -> [Name] -> DecQ
+mkBar tn xy nus xsys ks = closedTypeFamilyD tn (zipWith kindedTV xy $ (listK `appK`) . varK <$> ks) NoSig Nothing $
+	 (mkNil <$> [0 .. length nus - 1]) ++ [
+	tySynEqn Nothing
+		(foldl appT (conT tn) $ zipWith mkPat xy xsys)
+		((promotedTupleFromList (varT <$> xy) `promotedCons`
+			(foldl appT (conT tn) $ varT <$> xsys)))
+	]
+	where
+	mkNil i = tySynEqn Nothing
+		(foldl appT (conT tn) $ emptyOne nus i) promotedNilT
+	mkPat x xs = varT x `promotedCons` varT xs
+
+emptyOne :: [Name] -> Int -> [TypeQ]
+emptyOne ns i = (varT <$> take i ns) ++ [promotedNilT] ++ (varT <$> drop (i + 1) ns)
+
+foo :: DecsQ
+foo = [d|
+	type family Zip2 (xs :: [k0]) (ys :: [k1]) where
+		Zip2 '[] _ys = '[]
+		Zip2 _xs '[] = '[]
+		Zip2 (x ': xs) (y ': ys) = '(x, y) ': Zip2 xs ys |]
diff --git a/src/Data/TypeLevel/List/Unzip.hs b/src/Data/TypeLevel/List/Unzip.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypeLevel/List/Unzip.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE DataKinds, PolyKinds #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Data.TypeLevel.List.Unzip where
+
+import Prelude hiding (unzip)
+
+import Data.TypeLevel.List.TH
+import Data.TypeLevel.List.Push
+
+unzip `mapM` [2 .. 62]
diff --git a/src/Data/TypeLevel/List/Zip.hs b/src/Data/TypeLevel/List/Zip.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypeLevel/List/Zip.hs
@@ -0,0 +1,10 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE DataKinds, PolyKinds #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Data.TypeLevel.List.Zip where
+
+import Data.TypeLevel.List.TH
+
+mkZip `mapM` [2 .. 10]
diff --git a/src/Data/TypeLevel/Maybe.hs b/src/Data/TypeLevel/Maybe.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypeLevel/Maybe.hs
@@ -0,0 +1,23 @@
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE PatternSynonyms #-}
+{-# LANGUAGE StandaloneDeriving, GeneralizedNewtypeDeriving #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Data.TypeLevel.Maybe (M, pattern N, pattern J, Id(..)) where
+
+import Foreign.Storable
+import Data.TypeLevel.ParMaybe qualified as P
+
+newtype Id a = Id a deriving (Show, Eq, Ord, Storable)
+
+type M = P.M Id
+
+pattern N :: M 'Nothing
+pattern N <- P.N where N = P.N
+
+pattern J :: a -> M ('Just a)
+pattern J x <- (P.J (Id x)) where J x = P.J $ Id x
diff --git a/src/Data/TypeLevel/ParMaybe.hs b/src/Data/TypeLevel/ParMaybe.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypeLevel/ParMaybe.hs
@@ -0,0 +1,39 @@
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE GADTs, TypeFamilies #-}
+{-# LANGUAGE DataKinds, PolyKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE StandaloneDeriving #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Data.TypeLevel.ParMaybe (M(..), Map, maybe, map, nil) where
+
+import Prelude hiding (map, maybe)
+import Data.Kind
+
+data M (t :: k -> Type) (m :: Maybe k) where
+	N :: M t 'Nothing
+	J :: t a -> M t ('Just a)
+
+deriving instance Show (M t 'Nothing)
+deriving instance Show (t a) => Show (M t ('Just a))
+
+deriving instance Eq (M t 'Nothing)
+deriving instance Eq (t a) => Eq (M t ('Just a))
+
+deriving instance Ord (M t 'Nothing)
+deriving instance Ord (t a) => Ord (M t ('Just a))
+
+type family Map (f :: k -> l) (m :: Maybe k) where
+	Map _f 'Nothing = 'Nothing
+	Map f ('Just x) = 'Just (f x)
+
+maybe :: a -> (forall s . t s -> a) -> M t ms -> a
+maybe d _ N = d
+maybe _ f (J x) = f x
+
+map :: (forall s . t s -> t' (f s)) -> M t ms -> M t' (Map f ms)
+map _ N = N
+map f (J x) = J $ f x
+
+nil :: M (t :: k -> Type) 'Nothing
+nil = N
diff --git a/src/Data/TypeLevel/Tuple/Index.hs b/src/Data/TypeLevel/Tuple/Index.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypeLevel/Tuple/Index.hs
@@ -0,0 +1,10 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE DataKinds, PolyKinds #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Data.TypeLevel.Tuple.Index where
+
+import Data.TypeLevel.Tuple.Index.TH
+
+uncurry mkI `mapM` [ (i, n) | n <- [2 .. 15], i <- [0 .. n - 1] ]
diff --git a/src/Data/TypeLevel/Tuple/Index/TH.hs b/src/Data/TypeLevel/Tuple/Index/TH.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypeLevel/Tuple/Index/TH.hs
@@ -0,0 +1,39 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE DataKinds, PolyKinds #-}
+{-# LANGUAGE KindSignatures #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Data.TypeLevel.Tuple.Index.TH (mkI) where
+
+import Language.Haskell.TH
+
+mkI :: Int -> Int -> DecQ
+mkI i n = do
+	hd <- newName . concat $ take n varNames
+	ks <- newName `mapM` take n kindNames
+	vs <- newName `mapM` take n varNames
+	rawBar tn hd ks vs i
+	where tn = mkName $ "I" ++ show i ++ "_" ++ show n
+
+rawBar :: Name -> Name -> [Name] -> [Name] -> Int -> DecQ
+rawBar tn hd ks vs i = closedTypeFamilyD tn
+	[kindedTV hd
+		(tupleKind $ varK <$> ks)]
+	NoSig Nothing
+	[tySynEqn Nothing
+		(conT tn `appT` promotedTupleType (varT <$> vs))
+		(varT $ vs !! i)]
+
+promotedTupleType :: Quote m => [m Type] -> m Type
+promotedTupleType ts = foldl appT (promotedTupleT $ length ts) ts
+
+tupleKind :: [Kind] -> Kind
+tupleKind ks = foldl appK (tupleK $ length ks) ks
+
+varNames :: [String]
+varNames = ((: "") <$> ['a' .. 'z']) ++
+	[ cs ++ [c] | cs <- varNames, c <- ['a' .. 'z'] ]
+
+kindNames :: [String]
+kindNames = ('k' :) . show <$> [0 :: Int ..]
diff --git a/src/Data/TypeLevel/Tuple/MapIndex.hs b/src/Data/TypeLevel/Tuple/MapIndex.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypeLevel/Tuple/MapIndex.hs
@@ -0,0 +1,13 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE DataKinds, PolyKinds #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs -fno-warn-missing-export-lists #-}
+
+module Data.TypeLevel.Tuple.MapIndex where
+
+import Data.TypeLevel.Tuple.MapIndex.TH
+
+uncurry mkM `mapM` [ (i, n) | n <- [2 .. 10], i <- [0 .. n - 1] ]
+
+uncurry mkMTup `mapM` (concatMap (\n -> (, n) <$> mTupIndices n) [3 .. 8])
diff --git a/src/Data/TypeLevel/Tuple/MapIndex/TH.hs b/src/Data/TypeLevel/Tuple/MapIndex/TH.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypeLevel/Tuple/MapIndex/TH.hs
@@ -0,0 +1,89 @@
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Data.TypeLevel.Tuple.MapIndex.TH (mkM, mkMTup, mTupIndices) where
+
+import Language.Haskell.TH
+import Data.List qualified as L
+
+vars :: [String]
+vars = mkVar `concatMap` [1 ..]
+	where
+	mkVar :: Int -> [String]
+	mkVar 0 = [""]
+	mkVar n = [ cs ++ [c] | cs <- mkVar (n - 1), c <- ['a' .. 'z'] ]
+
+names :: [Q Name]
+names = newName <$> vars
+
+mkM :: Int -> Int -> Q Dec
+mkM i n = mkFoo' (mkName nm) i (take n names) -- [varT $ mkName "a", varT $ mkName "b"]
+	where
+	nm = 'M' : show i ++ "_" ++ show n
+
+mkFoo' :: Name -> Int -> [Q Name] -> Q Dec
+mkFoo' nm i nms = do
+	ts <- (VarT <$>) <$> sequence nms
+	ts' <- (varT <$>) <$> sequence nms
+	closedTypeFamilyD nm
+		[	kindedTV (mkName "tpl") (ListT `AppT` tuple ts) ] -- [VarT $ mkName "a", VarT $ mkName "b"]) ]
+		(KindSig $ ListT `AppT` (ts !! i))
+		Nothing
+		[	tySynEqn Nothing (conT nm `appT` promotedNilT) promotedNilT,
+			tySynEqn Nothing (conT nm `appT` bar ts')
+				$ promotedT '(:) `appT` (ts' !! i) `appT` (conT nm `appT` varT (mkName "rst"))
+			]
+
+bar :: [TypeQ] -> TypeQ
+bar ts = promotedT '(:) `appT` promotedTuple ts `appT` (varT $ mkName "rst")
+
+tuple :: [Type] -> Type
+tuple ts = foldl AppT (TupleT $ length ts) ts
+
+tuple' :: [Kind] -> Kind
+tuple' ts = foldl appK (tupleK $ length ts) ts
+
+promotedTuple :: [TypeQ] -> TypeQ
+promotedTuple ts = foldl appT (promotedTupleT $ length ts) ts
+
+mkMTup :: [Int] -> Int -> DecQ
+mkMTup is n = do
+	xyzs <- newName . concat $ take n varNames
+	vs <- newName `mapM` take n varNames
+	ks <- newName `mapM` take n kindNames
+	rst <- newName . concat $ take n varNames
+	bazRaw nm xyzs ks vs rst is
+	where
+	nm = mkName $ "M" ++ L.intercalate "'" (show <$> is) ++ "_" ++ show n
+
+bazRaw :: Name -> Name -> [Name] -> [Name] -> Name -> [Int] -> DecQ
+bazRaw tn xyzs ks vs rst is = closedTypeFamilyD tn
+	[kindedTV xyzs $ listK `appK` (tuple' $ varK <$> ks)]
+	noSig Nothing
+	[	tySynEqn Nothing
+			(conT tn `appT` promotedNilT)
+			promotedNilT,
+		tySynEqn Nothing
+			(conT tn `appT` (
+				promotedTuple (varT <$> vs) `promotedConsType`
+					varT rst ))
+			(promotedTuple (varT . (vs !!) <$> is) `promotedConsType`
+				(conT tn `appT` varT rst))
+		]
+
+promotedConsType :: Quote m => m Type -> m Type -> m Type
+promotedConsType a as = promotedConsT `appT` a `appT` as
+
+varNames :: [String]
+varNames = ((: "") <$> ['a' .. 'z']) ++ [ cs ++ [c] | cs <- varNames, c <- ['a' .. 'z'] ]
+
+kindNames :: [String]
+kindNames = ('k' :) . show <$> [0 :: Int ..]
+
+combinations :: [a] -> [[a]]
+combinations [] = [[]]
+combinations (x : xs) = combinations xs ++ ((x :) <$> combinations xs)
+
+mTupIndices :: Int -> [[Int]]
+mTupIndices n = filter ((`notElem` [0, 1, n]) . length) $ combinations [0 .. n - 1]
diff --git a/src/Data/TypeLevel/Tuple/Uncurry.hs b/src/Data/TypeLevel/Tuple/Uncurry.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypeLevel/Tuple/Uncurry.hs
@@ -0,0 +1,16 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE ScopedTypeVariables, TypeApplications #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE DataKinds, PolyKinds #-}
+{-# LANGUAGE KindSignatures, TypeOperators #-}
+{-# LANGUAGE AllowAmbiguousTypes #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE StandaloneDeriving #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Data.TypeLevel.Tuple.Uncurry where
+
+import Data.TypeLevel.Tuple.Uncurry.TH
+
+uc `mapM` [2 .. 62]
+showUc `mapM` [2 .. 62]
diff --git a/src/Data/TypeLevel/Tuple/Uncurry/TH.hs b/src/Data/TypeLevel/Tuple/Uncurry/TH.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypeLevel/Tuple/Uncurry/TH.hs
@@ -0,0 +1,57 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Data.TypeLevel.Tuple.Uncurry.TH (uc, showUc) where
+
+import Language.Haskell.TH
+
+uc :: Int -> DecQ
+uc n = do
+	t <- mkT
+	ss <- mkSs n
+	dataD (cxt []) (ucName n)
+		[	plainTV (mkName "t"), plainTV (mkName "ss") ]
+		Nothing
+		[	recGadtC
+				[ucName n]
+				[	varBangType (ucUnName n) (
+						(,)	<$> noSourceBang
+							<*> crrType t ss)]
+				(	conT (ucName n)
+						`appT` varT t
+						`appT` ucrrType ss ) ]
+		[]
+
+noSourceBang :: BangQ
+noSourceBang = bang noSourceUnpackedness noSourceStrictness
+
+showUc :: Int -> DecQ
+showUc n = do
+	t <- mkT
+	ss <- mkSs n
+	standaloneDerivD
+		(cxt [	conT ''Show `appT` crrType t ss ])
+		(conT ''Show `appT` (
+			conT (ucName n)
+				`appT` varT t `appT` ucrrType ss ))
+
+ucName :: Int -> Name
+ucName = mkName . ("U" ++) . show
+
+ucUnName :: Int -> Name
+ucUnName = mkName . ("unU" ++) . show
+
+mkT :: Q Name
+mkT = newName "t"
+
+mkSs :: Int -> Q [Name]
+mkSs n = (newName . ("s" ++) . show) `mapM` [1 .. n]
+
+crrType :: Name -> [Name] -> TypeQ
+crrType t = foldl appT (varT t) . map varT -- varT t `appT` varT (mkName "s1") `appT` varT (mkName "s2")
+
+ucrrType :: [Name] -> Q Type
+ucrrType = pTupTN -- pTupT2 (varT $ mkName "s1") (varT $ mkName "s2")
+
+pTupTN :: [Name] -> TypeQ
+pTupTN ns = foldl appT (promotedTupleT $ length ns) $ map varT ns
diff --git a/src/Data/TypeLevel/TypeVal.hs b/src/Data/TypeLevel/TypeVal.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypeLevel/TypeVal.hs
@@ -0,0 +1,7 @@
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE MultiParamTypeClasses, AllowAmbiguousTypes #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Data.TypeLevel.TypeVal where
+
+class T (t :: k) v where t :: v
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,2 @@
+main :: IO ()
+main = putStrLn "Test suite not yet implemented"
diff --git a/typelevel-tools-yj.cabal b/typelevel-tools-yj.cabal
new file mode 100644
--- /dev/null
+++ b/typelevel-tools-yj.cabal
@@ -0,0 +1,67 @@
+cabal-version: 1.12
+
+-- This file has been generated from package.yaml by hpack version 0.37.0.
+--
+-- see: https://github.com/sol/hpack
+
+name:           typelevel-tools-yj
+version:        0.1.0.6
+synopsis:       type level tools
+description:    Please see the README on GitHub at <https://github.com/YoshikuniJujo/typelevel-tools#readme>
+category:       Types
+homepage:       https://github.com/YoshikuniJujo/typelevel-tools#readme
+bug-reports:    https://github.com/YoshikuniJujo/typelevel-tools/issues
+author:         Yoshikuni Jujo
+maintainer:     yoshikuni.jujo@gmail.com
+copyright:      2023 Yoshikuni Jujo
+license:        BSD3
+license-file:   LICENSE
+build-type:     Simple
+extra-source-files:
+    README.md
+    CHANGELOG.md
+
+source-repository head
+  type: git
+  location: https://github.com/YoshikuniJujo/typelevel-tools
+
+library
+  exposed-modules:
+      Data.TypeLevel.Bool
+      Data.TypeLevel.List
+      Data.TypeLevel.List.Push
+      Data.TypeLevel.List.TH
+      Data.TypeLevel.List.Unzip
+      Data.TypeLevel.List.Zip
+      Data.TypeLevel.Maybe
+      Data.TypeLevel.ParMaybe
+      Data.TypeLevel.Tuple.Index
+      Data.TypeLevel.Tuple.Index.TH
+      Data.TypeLevel.Tuple.MapIndex
+      Data.TypeLevel.Tuple.MapIndex.TH
+      Data.TypeLevel.Tuple.Uncurry
+      Data.TypeLevel.Tuple.Uncurry.TH
+      Data.TypeLevel.TypeVal
+  other-modules:
+      Paths_typelevel_tools_yj
+  hs-source-dirs:
+      src
+  ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints
+  build-depends:
+      base >=4.7 && <5
+    , template-haskell <3
+  default-language: Haskell2010
+
+test-suite typelevel-tools-test
+  type: exitcode-stdio-1.0
+  main-is: Spec.hs
+  other-modules:
+      Paths_typelevel_tools_yj
+  hs-source-dirs:
+      test
+  ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
+  build-depends:
+      base >=4.7 && <5
+    , template-haskell <3
+    , typelevel-tools
+  default-language: Haskell2010
