diff --git a/TupleTH.hs b/TupleTH.hs
--- a/TupleTH.hs
+++ b/TupleTH.hs
@@ -1,31 +1,31 @@
 {-# LANGUAGE TemplateHaskell, FunctionalDependencies, MultiParamTypeClasses #-}
 {-# OPTIONS -Wall #-}
 
--- | Note: One-tuples are currently understood as just the original type by Template Haskell 
+-- | Note: One-tuples are currently understood as just the original type by Template Haskell
 -- (though this could be an undefined case which is not guaranteed to work this way?), so for example, we get
 --
 -- @ $('catTuples' 1 2) = \\x (y,z) -> (x,y,z) @
 module TupleTH(
     -- * Transformation
-        mapTuple, mapTuple', filterTuple, filterTuple', reindexTuple, reverseTuple, rotateTuple, subtuples, deleteAtTuple, takeTuple, dropTuple, safeDeleteTuple, 
+        mapTuple, mapTuple', filterTuple, filterTuple', reindexTuple, reverseTuple, rotateTuple, subtuples, deleteAtTuple, takeTuple, dropTuple, safeDeleteTuple, updateAtN,
     -- * Combination
         zipTuple, catTuples, uncatTuple, splitTupleAt,
     -- ** ZipWith
         zipTupleWith, zipTupleWith',
     -- * Construction
-        safeTupleFromList, tupleFromList, constTuple, 
+        safeTupleFromList, tupleFromList, constTuple,
     -- * Deconstruction
         proj, proj', elemTuple, tupleToList, sumTuple,
         findSuccessiveElementsSatisfying,
     -- ** Right folds
-        foldrTuple, foldrTuple', 
-        foldr1Tuple, foldr1Tuple', 
+        foldrTuple, foldrTuple',
+        foldr1Tuple, foldr1Tuple',
     -- ** Left folds
-        foldlTuple, foldlTuple', 
-        foldl1Tuple, foldl1Tuple', 
+        foldlTuple, foldlTuple',
+        foldl1Tuple, foldl1Tuple',
     -- ** Predicates
         andTuple, orTuple,
-        anyTuple, anyTuple', 
+        anyTuple, anyTuple',
         allTuple, allTuple',
     -- * Monadic/applicative
         sequenceTuple, sequenceATuple,
@@ -44,7 +44,7 @@
 import Data.List
 
 
--- | Makes a homogenous tuple type of the given size and element type 
+-- | Makes a homogenous tuple type of the given size and element type
 --
 -- > $(htuple 2) [t| Char |] = (Char,Char)
 htuple ::  Int -> TypeQ -> TypeQ
@@ -57,7 +57,7 @@
 withys = withNames "_y"
 
 newNames ::  String -> Int -> Q [Name]
-newNames stem n = sequence [newName (stem++show i) | i <- [ 1::Int .. n ]] 
+newNames stem n = sequence [newName (stem++show i) | i <- [ 1::Int .. n ]]
 
 withNames :: String -> Int -> (PatQ -> [ExpQ] -> Q a) -> Q a
 withNames stem n body = withNames' stem n (body . tupP)
@@ -65,7 +65,7 @@
 withNames' :: String -> Int -> ([PatQ] -> [ExpQ] -> Q a) -> Q a
 withNames' _ n _ | n < 0 = fail ("Negative tuple size: "++show n)
 withNames' stem n body = do
-    names <- newNames stem n 
+    names <- newNames stem n
     body (fmap varP names) (fmap varE names)
 
 
@@ -82,7 +82,7 @@
 appE2 ::  ExpQ -> ExpQ -> ExpQ -> ExpQ
 appE2 f x y = f `appE` x `appE` y
 
--- | Converts an expression-level function to a function expression 
+-- | Converts an expression-level function to a function expression
 liftExpFun ::  String -> (ExpQ -> ExpQ) -> Q Exp
 liftExpFun argNameStem f = do
     argName <- newName argNameStem
@@ -90,17 +90,17 @@
 
 
 
--- | Like 'zip'. 
+-- | Like 'zip'.
 --
--- Type of the generated expression: 
+-- Type of the generated expression:
 --
 -- > (a1, a2, ..) -> (b1, b2, ..) -> ((a1,b1), (a2,b2), ..)
 zipTuple ::  Int -> Q Exp
 zipTuple n = zipTupleWith' n (conE (tupleDataName 2))
 
--- | Like 'zipWith'. 
+-- | Like 'zipWith'.
 --
--- Type of the generated expression:  
+-- Type of the generated expression:
 --
 -- > (a -> b -> c) -> (a, ..) -> (b, ..) -> (c, ..)
 zipTupleWith ::  Int -> ExpQ
@@ -110,8 +110,8 @@
 -- | Takes the zipping function as a quoted expression. See 'mapTuple'' for how this can be useful.
 zipTupleWith' :: Int -> ExpQ -> ExpQ
 zipTupleWith' n f =
-    withNames2 "x" "y" n 
-        (\xsp xes ysp yes -> 
+    withNames2 "x" "y" n
+        (\xsp xes ysp yes ->
             lamE [xsp,ysp] (tupE (zipWith (appE2 f) xes yes)))
 
 
@@ -122,9 +122,9 @@
       -> ExpQ
 proj n i = do
     x <- newName "_x"
-    lam1E (tupP (replicate i wildP ++ [ varP x ] ++ replicate (n-i-1) wildP)) (varE x) 
-    
--- | Type of the generated expression: 
+    lam1E (tupP (replicate i wildP ++ [ varP x ] ++ replicate (n-i-1) wildP)) (varE x)
+
+-- | Type of the generated expression:
 --
 -- > (a -> r -> r) -> r -> (a, ..) -> r
 foldrTuple ::  Int -> ExpQ
@@ -134,9 +134,9 @@
 foldrTuple' :: Int -> ExpQ -> ExpQ
 foldrTuple' n c = do
     z <- newName "_z"
-    withxs n (\xsp xes -> lamE [varP z, xsp] (foldr (appE2 c) (varE z) xes)) 
+    withxs n (\xsp xes -> lamE [varP z, xsp] (foldr (appE2 c) (varE z) xes))
 
--- | Type of the generated expression: 
+-- | Type of the generated expression:
 --
 -- > (a -> a -> a) -> (a, ..) -> a
 foldr1Tuple ::  Int -> ExpQ
@@ -148,7 +148,7 @@
 foldr1Tuple' ::  Int -> ExpQ -> Q Exp
 foldr1Tuple' n c = withxs n (\xsp xes -> lam1E xsp (foldr1 (appE2 c) xes))
 
--- | Type of the generated expression: 
+-- | Type of the generated expression:
 --
 -- > (r -> a -> r) -> r -> (a, ..) -> r
 foldlTuple ::  Int -> ExpQ
@@ -159,9 +159,9 @@
 foldlTuple' :: Int -> ExpQ -> ExpQ
 foldlTuple' n c = do
     z <- newName "_z"
-    withxs n (\xsp xes -> lamE [varP z, xsp] (foldl (appE2 c) (varE z) xes)) 
+    withxs n (\xsp xes -> lamE [varP z, xsp] (foldl (appE2 c) (varE z) xes))
 
--- | Type of the generated expression: 
+-- | Type of the generated expression:
 --
 -- > (a -> a -> a) -> (a, ..) -> a
 foldl1Tuple ::  Int -> ExpQ
@@ -172,7 +172,7 @@
 foldl1Tuple' ::  Int -> ExpQ -> Q Exp
 foldl1Tuple' n c = withxs n (\xsp xes -> lam1E xsp (foldl1 (appE2 c) xes))
 
--- | Type of the generated expression: 
+-- | Type of the generated expression:
 --
 -- > (a -> Bool) -> (a, ..) -> [a]
 filterTuple ::  Int -> ExpQ
@@ -181,24 +181,24 @@
 
 -- | Takes the predicate as a quoted expression. See 'mapTuple'' for how this can be useful.
 filterTuple' ::  Int -> ExpQ -> ExpQ
-filterTuple' n p = withxs n (\xsp xes -> lamE [xsp] (go xes)) 
+filterTuple' n p = withxs n (\xsp xes -> lamE [xsp] (go xes))
     where
         go []       = [| [] |]
         go [x]      = [| if $(p) $(x) then [$(x)] else [] |]
-        go (x:xs)   = [| (if $(p) $(x) then ($(x) :) else id) $(go xs) |] 
+        go (x:xs)   = [| (if $(p) $(x) then ($(x) :) else id) $(go xs) |]
 
-      
 
--- | Type of the generated expression: 
+
+-- | Type of the generated expression:
 --
 -- > (a -> b) -> (a, ..) -> (b, ..)
 mapTuple :: Int -> ExpQ
 mapTuple n = liftExpFun "f" (mapTuple' n)
 
 
--- | Takes the mapping as a quoted expression. This can sometimes produce an expression that typechecks when the analogous expression using 'filterTuple' does not, e.g.: 
+-- | Takes the mapping as a quoted expression. This can sometimes produce an expression that typechecks when the analogous expression using 'filterTuple' does not, e.g.:
 --
--- > $(mapTuple 2) Just        ((),"foo") -- Type error 
+-- > $(mapTuple 2) Just        ((),"foo") -- Type error
 -- > $(mapTuple' 2 [| Just |]) ((),"foo") -- OK
 mapTuple' ::  Int -> ExpQ -> Q Exp
 mapTuple' n f = withxs n (\xsp xes ->
@@ -209,7 +209,7 @@
 smatch ::  PatQ -> ExpQ -> MatchQ
 smatch p e = match p (normalB e) []
 
--- | Type of the generated expression: 
+-- | Type of the generated expression:
 --
 -- > [a] -> Maybe (a, ..)
 safeTupleFromList ::  Int -> Q Exp
@@ -217,14 +217,14 @@
     xns <- newNames "_x" n
     let xps = varP <$> xns
         xes = varE <$> xns
-    xs <- newName "_xs" 
+    xs <- newName "_xs"
     lam1E (varP xs) (caseE (varE xs)
                        [ smatch (listP xps) (conE 'Just `appE` (tupE xes))
                        , smatch wildP (conE 'Nothing)
                        ])
 
 
--- | Type of the generated expression: 
+-- | Type of the generated expression:
 --
 -- > [a] -> (a, ..)
 --
@@ -275,25 +275,25 @@
 tupleToList n = [| $(foldrTuple' n (conE '(:))) [] |]
 
 
--- | Type of the generated expression: 
+-- | Type of the generated expression:
 --
 -- > (a1, ..) -> (b1, ..) -> (a1, .., b1, ..)
 catTuples :: Int -> Int -> Q Exp
 catTuples n m = withxs n (\xsp xes -> withys m (\ysp yes ->
     lamE [xsp,ysp] (tupE (xes ++ yes))))
 
--- | @uncatTuple n m = 'splitTupleAt' (n+m) n 
+-- | @uncatTuple n m = 'splitTupleAt' (n+m) n@
 --
--- @uncatTuple n m@ is the inverse function of @uncurry (catTuples n m)@. 
+-- @uncatTuple n m@ is the inverse function of @uncurry (catTuples n m)@.
 uncatTuple :: Int -> Int -> Q Exp
-uncatTuple n m = splitTupleAt (n+m) n 
+uncatTuple n m = splitTupleAt (n+m) n
 
--- | @splitTupleAt n i@ => @\(x_0, ..., x_{n-1}) -> ((x_0, ..., x_{i-1}),(x_i, ..., x_{n-1})@ 
+-- | @splitTupleAt n i@ => @\\(x_0, ..., x_{n-1}) -> ((x_0, ..., x_{i-1}),(x_i, ..., x_{n-1})@
 splitTupleAt :: Int -> Int -> Q Exp
-splitTupleAt n i = 
- withxs n (\xsp xes -> 
+splitTupleAt n i =
+ withxs n (\xsp xes ->
     case splitAt i xes of
-         (l,r) -> lam1E xsp (tupE [tupE l, tupE r])) 
+         (l,r) -> lam1E xsp (tupE [tupE l, tupE r]))
 
 
 
@@ -310,7 +310,7 @@
 reindexTuple n is = withNames' "x" n (\xps xes ->
     let
         iset = Set.fromList is
-        xsp' = fmap (\(p,i) -> if i `member` iset then p else wildP) 
+        xsp' = fmap (\(p,i) -> if i `member` iset then p else wildP)
                     (zip xps [0..])
 
     in
@@ -321,7 +321,7 @@
 reverseTuple ::  Int -> Q Exp
 reverseTuple n = reindexTuple n (reverse [0..n-1])
 
--- | @rotateTuple n k@ creates a function which rotates an @n@-tuple rightwards by @k@ positions (@k@ may be negative or greater than @n-1@). 
+-- | @rotateTuple n k@ creates a function which rotates an @n@-tuple rightwards by @k@ positions (@k@ may be negative or greater than @n-1@).
 rotateTuple ::  Int -> Int -> Q Exp
 rotateTuple n k = reindexTuple n (fmap (`mod` n) [n-k, n-k+1 .. 2*n-k-1])
 
@@ -335,27 +335,27 @@
 
 -- | Like 'sequence'.
 sequenceTuple ::  Int -> Q Exp
-sequenceTuple 0 = [| return () |] 
+sequenceTuple 0 = [| return () |]
 sequenceTuple 1 = [| id :: Monad m => m a -> m a |]
-sequenceTuple n = 
-    withxs n (\xsp xes -> 
-        lam1E xsp (foldl (\x y -> [| $(x) `ap` $(y) |]) 
+sequenceTuple n =
+    withxs n (\xsp xes ->
+        lam1E xsp (foldl (\x y -> [| $(x) `ap` $(y) |])
                          [| $(conE $ tupleDataName n) `liftM` $(head xes) |]
                          (tail xes)))
 
 -- | Like 'sequenceA'.
 sequenceATuple ::  Int -> Q Exp
-sequenceATuple 0 = [| pure () |] 
+sequenceATuple 0 = [| pure () |]
 sequenceATuple 1 = [| id :: Applicative f => f a -> f a |]
-sequenceATuple n = 
-    withxs n (\xsp xes -> 
-        lam1E xsp (foldl (\x y -> [| $(x) <*> $(y) |]) 
+sequenceATuple n =
+    withxs n (\xsp xes ->
+        lam1E xsp (foldl (\x y -> [| $(x) <*> $(y) |])
                          [| $(conE $ tupleDataName n) <$> $(head xes) |]
                          (tail xes)))
 
 descendingMultiindices :: Int -> Int -> [[Int]]
-descendingMultiindices _ 0 = [[]] 
-descendingMultiindices n 1 = fmap (:[]) [0..n-1] 
+descendingMultiindices _ 0 = [[]]
+descendingMultiindices n 1 = fmap (:[]) [0..n-1]
 descendingMultiindices n k | k < 0 = error ("Internal error in tuple-th: descendingMultiindices "++show n++" "++show k)
 descendingMultiindices n k = [ i:is | is <- descendingMultiindices (n-1) (k-1),
                                       i <- [head is+1,head is+2 .. n-1] ]
@@ -366,38 +366,38 @@
 subtuples n k = withxs n (\xsp xes ->
     let
         subtupleE :: [Int] -> ExpQ
-        subtupleE = tupE . fmap (xes !!) 
+        subtupleE = tupE . fmap (xes !!)
     in
         lam1E xsp (tupE (fmap (subtupleE . reverse) (descendingMultiindices n k))))
 
 -- class Tuple as a | as -> a where
 --     filterTuple :: (a -> Bool) -> as -> [a]
--- 
+--
 -- class MapTuple as a bs b | as -> a, bs -> b where
 --     mapTuple :: (a -> b) -> as -> bs
 
 -- mkTuple :: Int -> DecsQ
 -- mkTuple n = do
 --   let a = varT (mkName "a")
---                         
---     
+--
+--
 --   sequence
---     [ instanceD (cxt []) (conT ''Tuple `appT` ht n a `appT` a)  
+--     [ instanceD (cxt []) (conT ''Tuple `appT` ht n a `appT` a)
 --                 [valD (varP 'filterTuple) (normalB (filterTuple n)) []]
 --     ]
--- 
+--
 
 
--- | Generates a function which takes a 'Num' @i@ and a homogenous tuple of size @n@ and deletes the @i@-th (0-based) element of the tuple. 
+-- | Generates a function which takes a 'Num' @i@ and a homogenous tuple of size @n@ and deletes the @i@-th (0-based) element of the tuple.
 deleteAtTuple :: Int -> Q Exp
 deleteAtTuple n = do
     i <- newName "_i"
-    lam1E (varP i) $ 
+    lam1E (varP i) $
         withxs n (\xsp xes ->
 
                 let
-                    matches0 = [ match 
-                                    (litP (integerL j))  
+                    matches0 = [ match
+                                    (litP (integerL j))
                                     (normalB . tupE . deleteAt j $ xes)
                                     []
                                 | j <- [0 .. fromIntegral n -1] ]
@@ -405,10 +405,10 @@
                     errmsg1 = "deleteAtTuple "++show n++" "
                     errmsg2 = ": index out of bounds"
 
-                    matches = matches0 ++ [ 
-                                match wildP (normalB 
+                    matches = matches0 ++ [
+                                match wildP (normalB
                                     [| error (errmsg1 ++ show $(varE i) ++ errmsg2) |])
-                                            [] ] 
+                                            [] ]
                 in
                     lam1E xsp $ caseE (varE i) matches)
 
@@ -419,11 +419,11 @@
         deleteAt _ _ = assert False undefined
 
 
--- | @takeTuple n i = \(x_0, ..., x_{n-1}) -> (x_0, ..., x_{m-1})@
+-- | @takeTuple n i = \\(x_0, ..., x_{n-1}) -> (x_0, ..., x_{i-1})@
 takeTuple :: Int -> Int -> Q Exp
-takeTuple n i = reindexTuple n [0..i-1] 
+takeTuple n i = reindexTuple n [0..i-1]
 
--- | @dropTuple n i = \(x_0, ..., x_{n-1}) -> (x_i, ..., x_{n-1})@
+-- | @dropTuple n i = \\(x_0, ..., x_{n-1}) -> (x_i, ..., x_{n-1})@
 dropTuple :: Int -> Int -> Q Exp
 dropTuple n i = reindexTuple n [i..n-1]
 
@@ -435,7 +435,7 @@
 -- | @safeDeleteTuple n@ generates a function analogous to 'delete' that takes an element and an @n@-tuple and maybe returns an @n-1@-tuple (if and only if the element was found).
 safeDeleteTuple :: Int -> Q Exp
 safeDeleteTuple n = do
-    e <- newName "_deletee" 
+    e <- newName "_deletee"
     withxs n (\xsp xes ->
         lamE [varP e, xsp] (
 
@@ -443,15 +443,12 @@
                 ixes = zip [0::Int ..] xes
 
                 ges = map (\(i,xe) ->
-                            normalGE  
+                            normalGE
                                 [| $(varE e) == $(xe) |]
-                                [| Just $((tupE . map snd . filter ((/= i) . fst)) ixes) |] 
+                                [| Just $((tupE . map snd . filter ((/= i) . fst)) ixes) |]
                           )
                            ixes
-                        
 
-                last_ge = normalGE [|otherwise|] [|Nothing|]
-
             in
                 cond ges [|Nothing|]))
 
@@ -487,16 +484,27 @@
     withxs n (\xsp xes ->
         lamE [varP r, xsp]
             (cond
-                [ normalGE [| $(varE r) $(x0) $(x1) |] 
+                [ normalGE [| $(varE r) $(x0) $(x1) |]
                            [| Just ($(litE . integerL $ i) :: Int) |]
 
                     |
                         (i,x0,x1) <- zip3 [0..] xes (drop 1 xes) ]
                 [|Nothing|]))
-                
 
 
+-- | Generates a function modifying a single element of a tuple.
+updateAtN :: Int -- ^ Length of the input tuple
+          -> Int -- ^ 0-based index of the element to be modified
+          -> Q Exp -- ^ (b -> c) -> (a1,a2,b,a3,a4) -> (a1,a2,c,a3,a4)
+updateAtN n element = do
+  mapFunction <- newName "_f"
+  withxs n (\xsp xes -> do
 
-            
+    when (element < 0 || element >= n) $
+      fail ("updateAtN "++show n++" "++show element++": Element index out of range")
 
+    let
+      (start, x:xs) = splitAt element xes
+      results = start ++ appE (varE mapFunction) x : xs
 
+    lamE [varP mapFunction] ( lamE [ xsp ] $ tupE results ))
diff --git a/tuple-th.cabal b/tuple-th.cabal
--- a/tuple-th.cabal
+++ b/tuple-th.cabal
@@ -1,5 +1,5 @@
 Name:                tuple-th
-Version:             0.2.4
+Version:             0.2.5
 Synopsis:            Generate (non-recursive) utility functions for tuples of statically known size
 Description:         Template Haskell functions for generating functions similar to those in Data.List for tuples of statically known size.
 License:             BSD3
