diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,18 @@
 Changelog
 =========
 
+Version 0.2.1.0
+---------------
+
+*July 6, 2020*
+
+<https://github.com/mstksg/mutable/releases/tag/v0.2.1.0>
+
+*   Use TH to generate tuple instances for `Mutable` up to 12.
+*   Use TH to generate `ListRefTuple` instances for lists up to length 12.
+    Previously the instances up to the maximum length of `Mutable` tuple
+    instances were missing.
+
 Version 0.2.0.0
 ---------------
 
diff --git a/mutable.cabal b/mutable.cabal
--- a/mutable.cabal
+++ b/mutable.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: b7384039190c92bb1ccdc49dabc8288ac734520f4aa13ad47f6893e933a83ebb
+-- hash: ffd197df55f7f93dd8ec419431fdd2c85526097855d397d55d17828e1eebbe95
 
 name:           mutable
-version:        0.2.0.0
+version:        0.2.1.0
 synopsis:       Automatic piecewise-mutable references for your types
 description:    Associate and generate "piecewise-mutable" versions for your composite data
                 types.  Think of it like a "generalized MVector for all ADTs".
@@ -44,6 +44,7 @@
       Data.Mutable.Branches
       Data.Mutable.Class
       Data.Mutable.Instances
+      Data.Mutable.Internal.TH
       Data.Mutable.Parts
   other-modules:
       Data.Mutable.Internal
@@ -58,6 +59,7 @@
     , microlens
     , primitive >=0.6.4
     , reflection
+    , template-haskell
     , transformers
     , vector
     , vinyl
diff --git a/src/Data/Mutable/Branches.hs b/src/Data/Mutable/Branches.hs
--- a/src/Data/Mutable/Branches.hs
+++ b/src/Data/Mutable/Branches.hs
@@ -60,10 +60,10 @@
 import           Control.Monad
 import           Control.Monad.Primitive
 import           Data.Generics.Product.Internal.HList
-import           Data.Kind
 import           Data.Maybe
 import           Data.Mutable.Class
 import           Data.Mutable.Instances
+import           Data.Mutable.Internal
 import           Data.Primitive.MutVar
 import           GHC.Generics
 import           GHC.OverloadedLabels
@@ -697,25 +697,3 @@
 -- | 'MutBranch' focusing on the 'Right' case of an 'Either'
 rightMB :: (Mutable s a, Mutable s b) => MutBranch s (Either a b) b
 rightMB = constrMB #_Right
-
-class ListRefTuple (s :: Type) (b :: Type) (as :: [Type]) | as s -> b where
-    tupledRef :: GL.Iso' (HList (MapRef s as)) b
-    tupledRef = GL.iso (listRefToTuple @s @b @as) (tupleToListRef @s @b @as)
-    {-# INLINE tupledRef #-}
-    tupleToListRef :: b -> HList (MapRef s as)
-    listRefToTuple :: HList (MapRef s as) -> b
-
-instance ListRefTuple s (UnitRef s) '[] where
-    tupleToListRef _ = Nil
-    listRefToTuple _ = UnitRef
-instance (Ref s a ~ ra) => ListRefTuple s ra '[a] where
-    tupleToListRef x = x :> Nil
-    listRefToTuple (x :> _) = x
-instance (Ref s a ~ ra, Ref s b ~ rb) => ListRefTuple s (ra, rb) '[a, b] where
-    tupleToListRef (x, y) = x :> y :> Nil
-    listRefToTuple (x :> y :> _) = (x, y)
-
-
-
-
-
diff --git a/src/Data/Mutable/Instances.hs b/src/Data/Mutable/Instances.hs
--- a/src/Data/Mutable/Instances.hs
+++ b/src/Data/Mutable/Instances.hs
@@ -1,19 +1,20 @@
-{-# LANGUAGE BangPatterns           #-}
-{-# LANGUAGE DeriveFoldable         #-}
-{-# LANGUAGE DeriveTraversable      #-}
-{-# LANGUAGE EmptyCase              #-}
-{-# LANGUAGE EmptyDataDeriving      #-}
-{-# LANGUAGE FlexibleContexts       #-}
-{-# LANGUAGE FlexibleInstances      #-}
-{-# LANGUAGE GADTs                  #-}
-{-# LANGUAGE LambdaCase             #-}
-{-# LANGUAGE MultiParamTypeClasses  #-}
-{-# LANGUAGE StandaloneDeriving     #-}
-{-# LANGUAGE TypeFamilies           #-}
-{-# LANGUAGE TypeInType             #-}
-{-# LANGUAGE TypeOperators          #-}
-{-# LANGUAGE UndecidableInstances   #-}
-{-# OPTIONS_GHC -fno-warn-orphans   #-}
+{-# LANGUAGE BangPatterns          #-}
+{-# LANGUAGE DeriveFoldable        #-}
+{-# LANGUAGE DeriveTraversable     #-}
+{-# LANGUAGE EmptyCase             #-}
+{-# LANGUAGE EmptyDataDeriving     #-}
+{-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE GADTs                 #-}
+{-# LANGUAGE LambdaCase            #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE StandaloneDeriving    #-}
+{-# LANGUAGE TemplateHaskell       #-}
+{-# LANGUAGE TypeFamilies          #-}
+{-# LANGUAGE TypeInType            #-}
+{-# LANGUAGE TypeOperators         #-}
+{-# LANGUAGE UndecidableInstances  #-}
+{-# OPTIONS_GHC -fno-warn-orphans  #-}
 
 -- |
 -- Module      : Data.Mutable.Instances
@@ -70,6 +71,7 @@
 import           Data.Generics.Product.Internal.HList      (HList(..))
 import           Data.Kind
 import           Data.Mutable.Internal
+import           Data.Mutable.Internal.TH
 import           Data.Ord
 import           Data.Primitive.Array
 import           Data.Primitive.ByteArray
@@ -361,42 +363,11 @@
     freezeRef (u , v ) = (,) <$> freezeRef u <*> freezeRef v
     copyRef   (u , v ) (!x, !y) = copyRef u x *> copyRef v y
     moveRef   (u , v ) ( x,  y) = moveRef u x *> moveRef v y
-    cloneRef  (x , y ) = (,) <$> cloneRef x   <*> cloneRef y
+    cloneRef  (u , v ) = (,) <$> cloneRef u   <*> cloneRef v
     unsafeThawRef   (!x, !y) = (,) <$> unsafeThawRef x   <*> unsafeThawRef y
     unsafeFreezeRef (u , v ) = (,) <$> unsafeFreezeRef u <*> unsafeFreezeRef v
 
--- | A 'Ref' of a tuple is a tuple of 'Ref's, for easy accessing.
-instance (Mutable s a, Mutable s b, Mutable s c) => Mutable s (a, b, c) where
-    type Ref s (a, b, c) = (Ref s a, Ref s b, Ref s c)
-    thawRef   (!x, !y, !z) = (,,) <$> thawRef x   <*> thawRef y   <*> thawRef z
-    freezeRef (u , v , w ) = (,,) <$> freezeRef u <*> freezeRef v <*> freezeRef w
-    copyRef   (u , v , w ) (!x, !y, !z) = copyRef u x *> copyRef v y *> copyRef w z
-    moveRef   (u , v , w ) ( x,  y,  z) = moveRef u x *> moveRef v y *> moveRef w z
-    cloneRef  (x , y , z ) = (,,) <$> cloneRef x   <*> cloneRef y   <*> cloneRef z
-    unsafeThawRef   (!x, !y, !z) = (,,) <$> unsafeThawRef x   <*> unsafeThawRef y   <*> unsafeThawRef z
-    unsafeFreezeRef (u , v , w ) = (,,) <$> unsafeFreezeRef u <*> unsafeFreezeRef v <*> unsafeFreezeRef w
-
--- | A 'Ref' of a tuple is a tuple of 'Ref's, for easy accessing.
-instance (Mutable s a, Mutable s b, Mutable s c, Mutable s d) => Mutable s (a, b, c, d) where
-    type Ref s (a, b, c, d) = (Ref s a, Ref s b, Ref s c, Ref s d)
-    thawRef   (!x, !y, !z, !a) = (,,,) <$> thawRef x   <*> thawRef y   <*> thawRef z   <*> thawRef a
-    freezeRef (u , v , w , j ) = (,,,) <$> freezeRef u <*> freezeRef v <*> freezeRef w <*> freezeRef j
-    copyRef   (u , v , w , j ) (!x, !y, !z, !a) = copyRef u x *> copyRef v y *> copyRef w z *> copyRef j a
-    moveRef   (u , v , w , j ) ( x,  y,  z,  a) = moveRef u x *> moveRef v y *> moveRef w z *> moveRef j a
-    cloneRef  (x , y , z , a ) = (,,,) <$> cloneRef x   <*> cloneRef y   <*> cloneRef z   <*> cloneRef a
-    unsafeThawRef   (!x, !y, !z, !a) = (,,,) <$> unsafeThawRef x   <*> unsafeThawRef y   <*> unsafeThawRef z   <*> unsafeThawRef a
-    unsafeFreezeRef (u , v , w , j ) = (,,,) <$> unsafeFreezeRef u <*> unsafeFreezeRef v <*> unsafeFreezeRef w <*> unsafeFreezeRef j
-
--- | A 'Ref' of a tuple is a tuple of 'Ref's, for easy accessing.
-instance (Mutable s a, Mutable s b, Mutable s c, Mutable s d, Mutable s e) => Mutable s (a, b, c, d, e) where
-    type Ref s (a, b, c, d, e) = (Ref s a, Ref s b, Ref s c, Ref s d, Ref s e)
-    thawRef   (!x, !y, !z, !a, !b) = (,,,,) <$> thawRef x   <*> thawRef y   <*> thawRef z   <*> thawRef a   <*> thawRef b
-    freezeRef (u , v , w , j , k ) = (,,,,) <$> freezeRef u <*> freezeRef v <*> freezeRef w <*> freezeRef j <*> freezeRef k
-    copyRef   (u , v , w , j , k ) (!x, !y, !z, !a, !b) = copyRef u x *> copyRef v y *> copyRef w z *> copyRef j a *> copyRef k b
-    moveRef   (u , v , w , j , k ) ( x,  y,  z,  a,  b) = moveRef u x *> moveRef v y *> moveRef w z *> moveRef j a *> moveRef k b
-    cloneRef  (x , y , z , a , b ) = (,,,,) <$> cloneRef x   <*> cloneRef y   <*> cloneRef z   <*> cloneRef a   <*> cloneRef b
-    unsafeThawRef   (!x, !y, !z, !a, !b) = (,,,,) <$> unsafeThawRef x   <*> unsafeThawRef y   <*> unsafeThawRef z   <*> unsafeThawRef a   <*> unsafeThawRef b
-    unsafeFreezeRef (u , v , w , j , k ) = (,,,,) <$> unsafeFreezeRef u <*> unsafeFreezeRef v <*> unsafeFreezeRef w <*> unsafeFreezeRef j <*> unsafeFreezeRef k
+mutableTuples [3..12]
 
 -- | 'Ref' for components in a vinyl 'Rec'.
 newtype RecRef s f a = RecRef { getRecRef :: Ref s (f a) }
@@ -454,16 +425,6 @@
     unsafeThawRef   = fmap toARec . unsafeThawRef   . fromARec
     unsafeFreezeRef = fmap toARec . unsafeFreezeRef . fromARec
 
--- | Useful type family to @'Ref' m@ over every item in a type-level list
---
--- @
--- ghci> :kind! MapRef IO '[Int, V.Vector Double]
--- '[ MutVar RealWorld Int, MVector RealWorld Double ]
--- @
-type family MapRef s as where
-    MapRef s '[] = '[]
-    MapRef s (a ': as) = Ref s a ': MapRef s as
-
 -- | The mutable reference of the 'HList' type from generic-lens.
 data HListRef :: Type -> [Type] -> Type where
     NilRef :: HListRef s '[]
@@ -499,3 +460,21 @@
       x :> xs -> (:!>) <$> unsafeThawRef x <*> unsafeThawRef xs
     unsafeFreezeRef = \case
       v :!> vs -> (:>) <$> unsafeFreezeRef v <*> unsafeFreezeRef vs
+
+-- ListRefTuple instances
+
+-- this one instance is the reason why we have to define a new typeclass
+-- instead of using 'ListRef' -- because of @'ListRef' s () '[]@.
+instance ListRefTuple s (UnitRef s) '[] where
+    tupleToListRef _ = Nil
+    listRefToTuple _ = UnitRef
+
+instance (Ref s a ~ ra) => ListRefTuple s ra '[a] where
+    tupleToListRef x = x :> Nil
+    listRefToTuple (x :> _) = x
+
+instance (Ref s a ~ ra, Ref s b ~ rb) => ListRefTuple s (ra, rb) '[a, b] where
+    tupleToListRef (x, y) = x :> y :> Nil
+    listRefToTuple (x :> y :> _) = (x, y)
+
+listRefTuples [3..12]
diff --git a/src/Data/Mutable/Internal.hs b/src/Data/Mutable/Internal.hs
--- a/src/Data/Mutable/Internal.hs
+++ b/src/Data/Mutable/Internal.hs
@@ -10,6 +10,7 @@
 {-# LANGUAGE RankNTypes             #-}
 {-# LANGUAGE ScopedTypeVariables    #-}
 {-# LANGUAGE StandaloneDeriving     #-}
+{-# LANGUAGE TypeApplications       #-}
 {-# LANGUAGE TypeFamilyDependencies #-}
 {-# LANGUAGE TypeInType             #-}
 {-# LANGUAGE TypeOperators          #-}
@@ -45,6 +46,9 @@
   -- ** Instances for Generics combinators themselves
   , GMutableRef(..)
   , MutSumF(..)
+  -- ** Needed for MutBranch
+  , ListRefTuple(..)
+  , MapRef
   ) where
 
 import           Control.Monad.Primitive
@@ -53,12 +57,14 @@
 import           Data.Bifunctor
 import           Data.Coerce
 import           Data.Foldable
+import           Data.Generics.Product.Internal.HList
 import           Data.Kind
 import           Data.List
 import           Data.Primitive.MutVar
 import           Data.Vinyl.Functor
 import           GHC.Generics
-import qualified Data.Vinyl.XRec           as X
+import qualified Data.GenericLens.Internal            as GL
+import qualified Data.Vinyl.XRec                      as X
 
 -- | An instance of @'Mutable' s a@ means that @a@ can be stored
 -- a mutable reference in a 'PrimMonad' @m@ (where @s@ is the mutable state
@@ -1265,3 +1271,20 @@
     => z (RefFor s)
     -> m (z Identity)
 unsafeFreezeHKD = fmap to . gUnsafeFreezeRef_ . from
+
+-- | Useful type family to @'Ref' m@ over every item in a type-level list
+--
+-- @
+-- ghci> :kind! MapRef IO '[Int, V.Vector Double]
+-- '[ MutVar RealWorld Int, MVector RealWorld Double ]
+-- @
+type family MapRef s as where
+    MapRef s '[] = '[]
+    MapRef s (a ': as) = Ref s a ': MapRef s as
+
+class ListRefTuple (s :: Type) (b :: Type) (as :: [Type]) | as s -> b where
+    tupledRef :: GL.Iso' (HList (MapRef s as)) b
+    tupledRef = GL.iso (listRefToTuple @s @b @as) (tupleToListRef @s @b @as)
+    {-# INLINE tupledRef #-}
+    tupleToListRef :: b -> HList (MapRef s as)
+    listRefToTuple :: HList (MapRef s as) -> b
diff --git a/src/Data/Mutable/Internal/TH.hs b/src/Data/Mutable/Internal/TH.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Mutable/Internal/TH.hs
@@ -0,0 +1,225 @@
+{-# LANGUAGE CPP             #-}
+{-# LANGUAGE TemplateHaskell #-}
+
+module Data.Mutable.Internal.TH (
+    mutableTuples
+  , listRefTuples
+  ) where
+
+import           Control.Monad
+import           Data.Generics.Product.Internal.HList
+import           Data.List
+import           Data.Mutable.Internal
+import           Language.Haskell.TH
+
+tyVarNames :: [String]
+tyVarNames = (:[]) <$> filter (/= 's') ['a' .. 'z']
+
+mutableTuples :: [Int] -> Q [Dec]
+mutableTuples = traverse mutableTuple
+
+listRefTuples :: [Int] -> Q [Dec]
+listRefTuples = traverse listRefTuple
+
+
+mutableTuple
+    :: Int
+    -> Q Dec
+mutableTuple n = do
+    valVars <- replicateM n (newName "x")
+    refVars <- replicateM n (newName "r")
+    -- instance (Mutable s a, Mutable s b, Mutable s c) => Mutable s (a, b, c) where
+    pure $ InstanceD
+      Nothing
+      (mutableS . VarT <$> tyVars)
+      (mutableS instHead)
+      [ refImpl
+      , thawImpl valVars
+      , freezeImpl refVars
+      , copyImpl refVars valVars
+      , moveImpl refVars valVars
+      , cloneImpl refVars
+      , unsafeThawImpl valVars
+      , unsafeFreezeImpl refVars
+      ]
+  where
+    tuplerT :: [Type] -> Type
+    tuplerT = applyAllT (TupleT n)
+    tupConE :: Exp
+    tupConE = ConE (tupleDataName n)
+
+    mutableS :: Type -> Type
+    mutableS = ((ConT ''Mutable `AppT` VarT (mkName "s")) `AppT`)
+    refS :: Type -> Type
+    refS = ((ConT ''Ref `AppT` VarT (mkName "s")) `AppT`)
+    tyVars :: [Name]
+    tyVars = mkName <$> take n tyVarNames
+    instHead :: Type
+    instHead = tuplerT $ VarT <$> tyVars
+    -- type Ref s (a, b, c) = (Ref s a, Ref s b, Ref s c)
+    refImpl :: Dec
+#if MIN_VERSION_template_haskell(2,15,0)
+    refImpl = TySynInstD
+            . TySynEqn Nothing (refS instHead)
+#else
+    refImpl = TySynInstD ''Ref
+            . TySynEqn [VarT (mkName "s"), instHead]
+#endif
+            $ tuplerT (refS . VarT <$> tyVars)
+    thawImpl :: [Name] -> Dec
+    thawImpl valVars = FunD 'thawRef [
+        Clause [TupP (BangP . VarP <$> valVars)]
+               (NormalB . liftApplyAllE tupConE $
+                  (VarE 'thawRef `AppE`) . VarE <$> valVars
+               )
+               []
+      ]
+    -- freezeRef (u , v , w ) = (,,) <$> freezeRef u <*> freezeRef v <*> freezeRef w
+    freezeImpl :: [Name] -> Dec
+    freezeImpl refVars = FunD 'freezeRef [
+        Clause [TupP (VarP <$> refVars)]
+               (NormalB . liftApplyAllE tupConE $
+                  (VarE 'freezeRef `AppE`) . VarE <$> refVars
+               )
+               []
+      ]
+    -- copyRef   (u , v , w ) (!x, !y, !z) = copyRef u x *> copyRef v y *> copyRef w z
+    copyImpl :: [Name] -> [Name] -> Dec
+    copyImpl refVars valVars = FunD 'copyRef [
+        Clause [ TupP (BangP . VarP <$> refVars)
+               , TupP (BangP . VarP <$> valVars)
+               ]
+               (NormalB . sequenceAllE $
+                  zipWith (\r v -> (VarE 'copyRef `AppE` VarE r) `AppE` VarE v) refVars valVars
+               )
+               []
+      ]
+    -- moveRef   (u , v , w ) ( x,  y,  z) = moveRef u x *> moveRef v y *> moveRef w z
+    moveImpl :: [Name] -> [Name] -> Dec
+    moveImpl refVars valVars = FunD 'moveRef [
+        Clause [ TupP (BangP . VarP <$> refVars)
+               , TupP (BangP . VarP <$> valVars)
+               ]
+               (NormalB . sequenceAllE $
+                  zipWith (\r v -> (VarE 'moveRef `AppE` VarE r) `AppE` VarE v) refVars valVars
+               )
+               []
+      ]
+    -- cloneRef  (u , v , w ) = (,,) <$> cloneRef u   <*> cloneRef v   <*> cloneRef w
+    cloneImpl :: [Name] -> Dec
+    cloneImpl refVars = FunD 'cloneRef [
+        Clause [TupP (VarP <$> refVars)]
+               (NormalB . liftApplyAllE tupConE $
+                  (VarE 'cloneRef `AppE`) . VarE <$> refVars
+               )
+               []
+      ]
+    -- unsafeThawRef   (!x, !y, !z) = (,,) <$> unsafeThawRef x   <*> unsafeThawRef y   <*> unsafeThawRef z
+    unsafeThawImpl :: [Name] -> Dec
+    unsafeThawImpl valVars = FunD 'unsafeThawRef [
+        Clause [TupP (BangP . VarP <$> valVars)]
+               (NormalB . liftApplyAllE tupConE $
+                  (VarE 'unsafeThawRef `AppE`) . VarE <$> valVars
+               )
+               []
+      ]
+    -- unsafeFreezeRef (u , v , w ) = (,,) <$> unsafeFreezeRef u <*> unsafeFreezeRef v <*> unsafeFreezeRef w
+    unsafeFreezeImpl :: [Name] -> Dec
+    unsafeFreezeImpl refVars = FunD 'unsafeFreezeRef [
+        Clause [TupP (VarP <$> refVars)]
+               (NormalB . liftApplyAllE tupConE $
+                  (VarE 'unsafeFreezeRef `AppE`) . VarE <$> refVars
+               )
+               []
+      ]
+
+listRefTuple
+    :: Int
+    -> Q Dec
+listRefTuple n = do
+    valVars <- replicateM n (newName "x")
+    -- instance (Ref s a ~ ra, Ref s b ~ rb) => ListRefTuple s (ra, rb) '[a, b] where
+    pure $ InstanceD
+      Nothing
+      (zipWith refConstr refVars tyVars)
+      (listRefTupleS (tuplerT (VarT <$> refVars)) `AppT`
+          (liftedList (VarT <$> tyVars))
+      )
+      [ tupToListImpl valVars
+      , listToTupImpl valVars
+      ]
+  where
+    tuplerT :: [Type] -> Type
+    tuplerT = applyAllT (TupleT n)
+    tupConE :: Exp
+    tupConE = ConE (tupleDataName n)
+
+    listRefTupleS :: Type -> Type
+    listRefTupleS = ((ConT ''ListRefTuple `AppT` VarT (mkName "s")) `AppT`)
+    refS :: Type -> Type
+    refS = ((ConT ''Ref `AppT` VarT (mkName "s")) `AppT`)
+    tyVarsStr :: [String]
+    tyVarsStr = take n tyVarNames
+    tyVars :: [Name]
+    tyVars = mkName <$> tyVarsStr
+    refVars :: [Name]
+    refVars = mkName . ("r" ++) <$> tyVarsStr
+
+    refConstr :: Name -> Name -> Pred
+    refConstr r v = (EqualityT `AppT` refS (VarT v))
+             `AppT` VarT r
+
+    -- tupleToListRef (x, y) = x :> y :> Nil
+    tupToListImpl :: [Name] -> Dec
+    tupToListImpl valVars = FunD 'tupleToListRef [
+        Clause [TupP (VarP <$> valVars)]
+               ( NormalB
+                      . foldr (\x y -> (ConE '(:>) `AppE` VarE x) `AppE` y) (ConE 'Nil)
+                      $ valVars
+               )
+               []
+      ]
+    -- listRefToTuple (x :> y :> _) = (x, y)
+    listToTupImpl :: [Name] -> Dec
+    listToTupImpl valVars = FunD 'listRefToTuple [
+        Clause [ foldr (\x y -> ConP '(:>) [VarP x, y]) (ConP 'Nil []) valVars
+               ]
+               ( NormalB . applyAllE tupConE $
+                    VarE <$> valVars
+               )
+               []
+      ]
+
+
+applyAllT
+    :: Type
+    -> [Type]
+    -> Type
+applyAllT = foldl' (\t m -> t `AppT` m)
+
+-- | liftApplyAllE f [x,y,z] = f <$> x <*> y <*> z
+liftApplyAllE
+    :: Exp
+    -> [Exp]
+    -> Exp
+liftApplyAllE = foldl' (\t m -> (VarE '(<*>) `AppE` t) `AppE` m)
+              . (VarE 'pure `AppE`)
+
+-- | applyAllE f [x,y,z] = f x y z
+applyAllE
+    :: Exp
+    -> [Exp]
+    -> Exp
+applyAllE = foldl' (\t m -> t `AppE` m)
+
+-- | sequenceAllE [x,y,z] = x *> y *> z
+sequenceAllE
+    :: [Exp]
+    -> Exp
+sequenceAllE = foldr1 (\x y -> (VarE '(*>) `AppE` x) `AppE` y)
+
+liftedList
+    :: [Type]
+    -> Type
+liftedList = foldr (\x y -> (PromotedConsT `AppT` x) `AppT` y) PromotedNilT
+
