diff --git a/src/Control/Applicative/HT.hs b/src/Control/Applicative/HT.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Applicative/HT.hs
@@ -0,0 +1,31 @@
+module Control.Applicative.HT where
+
+import qualified Data.Tuple.HT as Tuple
+
+import Control.Applicative (Applicative, liftA2, liftA3, (<$>), (<*>), )
+
+mapPair :: (Applicative f) => (a -> f c, b -> f d) -> (a,b) -> f (c,d)
+mapPair fg = uncurry (liftA2 (,)) . Tuple.mapPair fg
+
+mapTriple ::
+   (Applicative m) => (a -> m d, b -> m e, c -> m f) -> (a,b,c) -> m (d,e,f)
+mapTriple fgh = Tuple.uncurry3 (liftA3 (,,)) . Tuple.mapTriple fgh
+
+
+{-# INLINE liftA4 #-}
+liftA4 :: Applicative f =>
+   (a -> b -> c -> d -> e) ->
+   f a -> f b -> f c -> f d -> f e
+liftA4 f a b c d = f <$> a <*> b <*> c <*> d
+
+{-# INLINE liftA5 #-}
+liftA5 :: Applicative f =>
+   (a -> b -> c -> d -> e -> g) ->
+   f a -> f b -> f c -> f d -> f e -> f g
+liftA5 f a b c d e = f <$> a <*> b <*> c <*> d <*> e
+
+{-# INLINE liftA6 #-}
+liftA6 :: Applicative f =>
+   (a -> b -> c -> d -> e -> g -> h) ->
+   f a -> f b -> f c -> f d -> f e -> f g -> f h
+liftA6 f a b c d e g = f <$> a <*> b <*> c <*> d <*> e <*> g
diff --git a/src/Control/Functor/HT.hs b/src/Control/Functor/HT.hs
--- a/src/Control/Functor/HT.hs
+++ b/src/Control/Functor/HT.hs
@@ -28,6 +28,24 @@
 unzip3 :: Functor f => f (a, b, c) -> (f a, f b, f c)
 unzip3 x = (fmap fst3 x, fmap snd3 x, fmap thd3 x)
 
+
+mapFst :: Functor f => (a -> f c) -> (a, b) -> f (c, b)
+mapFst f ~(a,b) = fmap (flip (,) b) $ f a
+
+mapSnd :: Functor f => (b -> f c) -> (a, b) -> f (a, c)
+mapSnd f ~(a,b) = fmap ((,) a) $ f b
+
+
+mapFst3 :: Functor f => (a -> f d) -> (a,b,c) -> f (d,b,c)
+mapFst3 f ~(a,b,c) = fmap (\x -> (x,b,c)) $ f a
+
+mapSnd3 :: Functor f => (b -> f d) -> (a,b,c) -> f (a,d,c)
+mapSnd3 f ~(a,b,c) = fmap (\x -> (a,x,c)) $ f b
+
+mapThd3 :: Functor f => (c -> f d) -> (a,b,c) -> f (a,b,d)
+mapThd3 f ~(a,b,c) = fmap ((,,) a b) $ f c
+
+
 {- |
 Generalization of 'Data.List.HT.outerProduct'.
 -}
diff --git a/src/Control/Monad/HT.hs b/src/Control/Monad/HT.hs
--- a/src/Control/Monad/HT.hs
+++ b/src/Control/Monad/HT.hs
@@ -45,6 +45,15 @@
    in  aux m
 
 {- |
+I think this makes only sense in a lazy monad
+like @Trans.State.Lazy@ or @IO.Lazy@.
+-}
+iterate :: Monad m => (a -> m a) -> a -> m [a]
+iterate f =
+   let go x = lift (x:) $ go =<< f x
+   in  go
+
+{- |
 Lazy monadic conjunction.
 That is, when the first action returns @False@,
 then @False@ is immediately returned, without running the second action.
@@ -84,6 +93,7 @@
 chain :: (Monad m) => [a -> m a] -> (a -> m a)
 chain = foldr (flip (<=<)) return
 
+-- there is also mfilter, but this should be part of Control.Monad.Plus
 filter :: Monad m => (a -> m Bool) -> [a] -> m [a]
 filter = M.filterM
 
diff --git a/src/Data/Bits/HT.hs b/src/Data/Bits/HT.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Bits/HT.hs
@@ -0,0 +1,20 @@
+module Data.Bits.HT where
+
+import Data.Bits (Bits, shiftL, shiftR)
+
+
+infixl 7 .<<., .>>.
+
+{- |
+Infix variant of 'shiftL'.
+Precedence is chosen like multiplication since @a .<<. k == a * 2^k@.
+-}
+(.<<.) :: Bits a => a -> Int -> a
+(.<<.) = shiftL
+
+{- |
+Infix variant of 'shiftR'.
+Precedence is chosen like division since @a .>>. k == a / 2^k@.
+-}
+(.>>.) :: Bits a => a -> Int -> a
+(.>>.) = shiftR
diff --git a/src/Data/List/HT.hs b/src/Data/List/HT.hs
--- a/src/Data/List/HT.hs
+++ b/src/Data/List/HT.hs
@@ -11,6 +11,7 @@
    -- * Split
    L.chop,
    L.breakAfter,
+   L.takeUntil,
    L.segmentAfter,
    L.segmentBefore,
    L.segmentAfterMaybe,
@@ -26,10 +27,12 @@
    -- * List processing starting at the end
    L.dropRev,
    L.takeRev,
-   L.dropWhileRev,
-   L.takeWhileRev,
+   L.splitAtRev,
+   dropWhileRev,
+   takeWhileRev,
    -- * List processing with Maybe and Either
    L.maybePrefixOf,
+   L.maybeSuffixOf,
    L.partitionMaybe,
    L.takeWhileJust,
    L.unzipEithers,
@@ -63,3 +66,12 @@
    ) where
 
 import qualified Data.List.HT.Private as L
+import qualified Data.List.Reverse.StrictElement as Rev
+
+{-# DEPRECATED dropWhileRev "Use dropWhile from Data.List.Reverse.StrictElement or Data.List.Reverse.StrictSpine instead" #-}
+dropWhileRev :: (a -> Bool) -> [a] -> [a]
+dropWhileRev = Rev.dropWhile
+
+{-# DEPRECATED takeWhileRev "Use takeWhile from Data.List.Reverse.StrictElement or Data.List.Reverse.StrictSpine instead" #-}
+takeWhileRev :: (a -> Bool) -> [a] -> [a]
+takeWhileRev = Rev.takeWhile
diff --git a/src/Data/List/HT/Private.hs b/src/Data/List/HT/Private.hs
--- a/src/Data/List/HT/Private.hs
+++ b/src/Data/List/HT/Private.hs
@@ -5,10 +5,12 @@
 import Data.Maybe as Maybe (fromMaybe, catMaybes, )
 import Data.Maybe.HT       (toMaybe, )
 import Control.Monad       (guard, msum, )
+import Control.Applicative ((<*>), )
 import Data.Tuple.HT       (mapPair, mapFst, mapSnd, forcePair, swap, )
 
 import qualified Data.List.Key.Private   as Key
 import qualified Data.List.Match.Private as Match
+import qualified Data.List.Reverse.StrictElement as Rev
 
 import Prelude hiding (unzip, break, span, )
 
@@ -180,7 +182,7 @@
    in  recourse
 
 
-chopAtRun :: (Eq a) => (a -> Bool) -> [a] -> [[a]]
+chopAtRun :: (a -> Bool) -> [a] -> [[a]]
 chopAtRun p =
    let recourse [] = [[]]
        recourse y =
@@ -193,7 +195,10 @@
 Like 'break', but splits after the matching element.
 -}
 breakAfter :: (a -> Bool) -> [a] -> ([a], [a])
-breakAfter p =
+breakAfter = breakAfterRec
+
+breakAfterRec :: (a -> Bool) -> [a] -> ([a], [a])
+breakAfterRec p =
    let recourse [] = ([],[])
        recourse (x:xs) =
           mapFst (x:) $
@@ -202,8 +207,40 @@
             else recourse xs
    in  forcePair . recourse
 
+{-
+The use of 'foldr' might allow for fusion,
+but unfortunately this simple implementation would copy the tail of the list.
+-}
+breakAfterFoldr :: (a -> Bool) -> [a] -> ([a], [a])
+breakAfterFoldr p =
+   forcePair .
+   foldr
+      (\x yzs -> mapFst (x:) $ if p x then ([], uncurry (++) yzs) else yzs)
+      ([],[])
 
+breakAfterBreak :: (a -> Bool) -> [a] -> ([a], [a])
+breakAfterBreak p xs =
+   case break p xs of
+      (ys, []) -> (ys, [])
+      (ys, z:zs) -> (ys++[z], zs)
+
+breakAfterTakeUntil :: (a -> Bool) -> [a] -> ([a], [a])
+breakAfterTakeUntil p xs =
+   forcePair $
+   (\ys -> (map fst ys, maybe [] (snd . snd) $ viewR ys)) $
+   takeUntil (p . fst) $ zip xs $ tail $ tails xs
+
 {- |
+Take all elements until one matches.
+The matching element is returned, too.
+This is the key difference to @takeWhile (not . p)@.
+It holds @takeUntil p xs == fst (breakAfter p xs)@.
+-}
+takeUntil :: (a -> Bool) -> [a] -> [a]
+takeUntil p = foldr (\x ys -> x : if p x then [] else ys) []
+
+
+{- |
 Split the list after each occurence of a terminator.
 Keep the terminator.
 There is always a list for the part after the last terminator.
@@ -452,43 +489,39 @@
 dropRev :: Int -> [a] -> [a]
 dropRev n xs = Match.take (drop n xs) xs
 
-
 {- |
-Remove the longest suffix of elements satisfying p.
-In contrast to @reverse . dropWhile p . reverse@
-this works for infinite lists, too.
+@splitAtRev n xs == (dropRev n xs, takeRev n xs)@.
+It holds @xs == uncurry (++) (splitAtRev n xs)@
 -}
+splitAtRev :: Int -> [a] -> ([a], [a])
+splitAtRev n xs = Match.splitAt (drop n xs) xs
+
+
 dropWhileRev :: (a -> Bool) -> [a] -> [a]
 dropWhileRev p =
-   foldr (\x xs -> if p x && null xs then [] else x:xs) []
-
-dropWhileRev' :: (a -> Bool) -> [a] -> [a]
-dropWhileRev' p =
    concat . init . segmentAfter (not . p)
 
-{- |
-Alternative version of @reverse . takeWhile p . reverse@.
--}
-takeWhileRev :: (a -> Bool) -> [a] -> [a]
-takeWhileRev p =
+takeWhileRev0 :: (a -> Bool) -> [a] -> [a]
+takeWhileRev0 p =
    last . segmentAfter (not . p)
 
 {- |
 Doesn't seem to be superior to the naive implementation.
 -}
-takeWhileRev' :: (a -> Bool) -> [a] -> [a]
-takeWhileRev' p =
-   (\xs -> if fst (head xs)
-             then map snd xs
-             else []) .
-   last . Key.aux groupBy (==) p
+takeWhileRev1 :: (a -> Bool) -> [a] -> [a]
+takeWhileRev1 p =
+   (\mx ->
+      case mx of
+         Just (_, xs@((True,_):_)) -> map snd xs
+         _ -> []) .
+   viewR . Key.aux groupBy (==) p
 
 {- |
 However it is more inefficient,
 because of repeatedly appending single elements. :-(
 -}
-takeWhileRev'' :: (a -> Bool) -> [a] -> [a]
-takeWhileRev'' p =
+takeWhileRev2 :: (a -> Bool) -> [a] -> [a]
+takeWhileRev2 p =
    foldl (\xs x -> if p x then xs++[x] else []) []
 
 
@@ -498,12 +531,18 @@
 @maybePrefixOf xs ys@ is @Just zs@ if @xs@ is a prefix of @ys@,
 where @zs@ is @ys@ without the prefix @xs@.
 Otherwise it is @Nothing@.
+It is the same as 'Data.List.stripPrefix'.
 -}
 maybePrefixOf :: Eq a => [a] -> [a] -> Maybe [a]
 maybePrefixOf (x:xs) (y:ys) = guard (x==y) >> maybePrefixOf xs ys
 maybePrefixOf [] ys = Just ys
 maybePrefixOf _  [] = Nothing
 
+maybeSuffixOf :: Eq a => [a] -> [a] -> Maybe [a]
+maybeSuffixOf xs ys =
+   fmap reverse $ maybePrefixOf (reverse xs) (reverse ys)
+
+
 {- |
 Partition a list into elements which evaluate to @Just@ or @Nothing@ by @f@.
 
@@ -699,7 +738,7 @@
 transposeFill =
    unfoldr (\xs ->
       toMaybe (not (null xs))
-         (mapSnd (dropWhileRev null) $ unzipCons xs))
+         (mapSnd (Rev.dropWhile null) $ unzipCons xs))
 
 unzipCons :: [[a]] -> ([Maybe a], [[a]])
 unzipCons =
@@ -732,7 +771,7 @@
        zipConc (a:as) (b:bs) = (a++b) : zipConc as bs
        zipConc [] bs = bs
        zipConc as [] = as
-   in  y : zipConc ys (shear' (dropWhileRev null zs))
+   in  y : zipConc ys (shear' (Rev.dropWhile null zs))
               {- Dropping trailing empty lists is necessary,
                  otherwise finite lists are filled with empty lists. -}
 shear' [] = []
@@ -945,6 +984,13 @@
 -}
 mapAdjacent :: (a -> a -> b) -> [a] -> [b]
 mapAdjacent f xs = zipWith f xs (tail xs)
+
+{- |
+<http://mail.haskell.org/libraries/2016-April/026912.html>
+-}
+mapAdjacentPointfree :: (a -> a -> b) -> [a] -> [b]
+mapAdjacentPointfree f = zipWith f <*> tail
+
 
 {- |
 > mapAdjacent f a0 [(a1,b1), (a2,b2), (a3,b3)]
diff --git a/src/Data/List/Reverse/StrictElement.hs b/src/Data/List/Reverse/StrictElement.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/List/Reverse/StrictElement.hs
@@ -0,0 +1,44 @@
+{- |
+The functions in this module process the list formally from the end.
+Actually they traverse the list from the start and check every element.
+This way they are strict in the elements and lazy in the list spline.
+Thus you can apply them to infinite lists.
+Use these functions if the list is long or the test is cheap.
+-}
+module Data.List.Reverse.StrictElement where
+
+import Data.Tuple.HT (mapFst, mapSnd, forcePair, )
+
+import Prelude hiding (dropWhile, takeWhile, span, )
+
+
+{- |
+Remove the longest suffix of elements satisfying p.
+In contrast to @reverse . dropWhile p . reverse@
+this works for infinite lists, too.
+-}
+dropWhile :: (a -> Bool) -> [a] -> [a]
+dropWhile p =
+   foldr (\x xs -> if p x && null xs then [] else x:xs) []
+
+{- |
+Alternative version of @reverse . takeWhile p . reverse@.
+-}
+takeWhile :: (a -> Bool) -> [a] -> [a]
+takeWhile p =
+   snd .
+   foldr
+      (\x xys ->
+         (if p x && fst xys then mapSnd (x:) else mapFst (const False)) xys)
+      (True, [])
+
+{- |
+@span p xs == (dropWhile p xs, takeWhile p xs)@
+-}
+span :: (a -> Bool) -> [a] -> ([a], [a])
+span p =
+   forcePair .
+   foldr
+      (\x xys ->
+         (if p x && null (fst xys) then mapSnd else mapFst) (x:) xys)
+      ([], [])
diff --git a/src/Data/List/Reverse/StrictSpine.hs b/src/Data/List/Reverse/StrictSpine.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/List/Reverse/StrictSpine.hs
@@ -0,0 +1,41 @@
+{- |
+The functions in this module process the list from the end.
+They do not access elements at the beginning if not necessary.
+You can apply the function only to infinite lists.
+Use these functions if the list is short and the test is expensive.
+-}
+module Data.List.Reverse.StrictSpine where
+
+import Data.Tuple.HT (mapFst, mapSnd, forcePair, )
+
+import Prelude hiding (dropWhile, takeWhile, span, )
+
+
+{- |
+Like @reverse . List.dropWhile p . reverse@.
+-}
+dropWhile :: (a -> Bool) -> [a] -> [a]
+dropWhile p =
+   foldr (\x xs -> if null xs && p x then [] else x:xs) []
+
+{- |
+Like @reverse . List.takeWhile p . reverse@.
+-}
+takeWhile :: (a -> Bool) -> [a] -> [a]
+takeWhile p =
+   snd .
+   foldr
+      (\x xys ->
+         (if fst xys && p x then mapSnd (x:) else mapFst (const False)) xys)
+      (True, [])
+
+{- |
+@span p xs == (dropWhile p xs, takeWhile p xs)@
+-}
+span :: (a -> Bool) -> [a] -> ([a], [a])
+span p =
+   forcePair .
+   foldr
+      (\x xys ->
+         (if null (fst xys) && p x then mapSnd else mapFst) (x:) xys)
+      ([], [])
diff --git a/src/Data/String/HT.hs b/src/Data/String/HT.hs
--- a/src/Data/String/HT.hs
+++ b/src/Data/String/HT.hs
@@ -1,8 +1,14 @@
 module Data.String.HT where
 
+import qualified Data.List.Reverse.StrictSpine as Rev
 import Data.Char (isSpace, )
-import Data.List.HT (dropWhileRev, )
 
--- | remove leading and trailing spaces
+{- |
+Remove leading and trailing spaces.
+
+We use spine strict 'Rev.dropWhile' instead of the element strict version.
+This is more efficient for finite 'String's because 'isSpace' is expensive.
+The downside is that 'trim' does not work for infinite 'String's.
+-}
 trim :: String -> String
-trim = dropWhileRev isSpace . dropWhile isSpace
+trim = Rev.dropWhile isSpace . dropWhile isSpace
diff --git a/src/Data/Tuple/HT.hs b/src/Data/Tuple/HT.hs
--- a/src/Data/Tuple/HT.hs
+++ b/src/Data/Tuple/HT.hs
@@ -4,6 +4,7 @@
    mapFst,
    mapSnd,
    swap,
+   sortPair,
    forcePair,
 
    -- * Triple
@@ -36,3 +37,7 @@
 {-# INLINE curry3 #-}
 curry3 :: ((a, b, c) -> d) -> a -> b -> c -> d
 curry3 f a b c = f (a,b,c)
+
+sortPair, _sortPairMinMax :: (Ord a) => (a,a) -> (a,a)
+sortPair (x,y) = if x<=y then (x,y) else (y,x)
+_sortPairMinMax (x,y) = (min x y, max x y)
diff --git a/src/Data/Tuple/Lazy.hs b/src/Data/Tuple/Lazy.hs
--- a/src/Data/Tuple/Lazy.hs
+++ b/src/Data/Tuple/Lazy.hs
@@ -15,12 +15,12 @@
 where one variant is definitely better than the other one.
 -}
 {-
-Instead of lazy pattern matching with \code{(x,y)}
+Instead of lazy pattern matching with \code{(a,b)}
 we may use \function{fst} and \function{snd}.
 -}
 {-# INLINE mapPair #-}
 mapPair :: (a -> c, b -> d) -> (a,b) -> (c,d)
-mapPair ~(f,g) ~(x,y) = (f x, g y)
+mapPair ~(f,g) ~(a,b) = (f a, g b)
 
 -- | 'Control.Arrow.first'
 {-# INLINE mapFst #-}
@@ -32,21 +32,25 @@
 mapSnd :: (b -> c) -> (a,b) -> (a,c)
 mapSnd f ~(a,b) = (a, f b)
 
+{-# INLINE zipWithPair #-}
+zipWithPair :: (a -> c -> e, b -> d -> f) -> (a,b) -> (c,d) -> (e,f)
+zipWithPair ~(e,f) ~(a,b) ~(c,d) = (e a c, f b d)
 
+
 {-# INLINE swap #-}
 swap :: (a,b) -> (b,a)
-swap ~(x,y) = (y,x)
+swap ~(a,b) = (b,a)
 
 {-# INLINE forcePair #-}
 forcePair :: (a,b) -> (a,b)
-forcePair ~(x,y) = (x,y)
+forcePair ~(a,b) = (a,b)
 
 
 -- * Triple
 
 {-# INLINE mapTriple #-}
 mapTriple :: (a -> d, b -> e, c -> f) -> (a,b,c) -> (d,e,f)
-mapTriple ~(f,g,h) ~(x,y,z) = (f x, g y, h z)
+mapTriple ~(f,g,h) ~(a,b,c) = (f a, g b, h c)
 
 {-# INLINE mapFst3 #-}
 mapFst3 :: (a -> d) -> (a,b,c) -> (d,b,c)
@@ -59,6 +63,11 @@
 {-# INLINE mapThd3 #-}
 mapThd3 :: (c -> d) -> (a,b,c) -> (a,b,d)
 mapThd3 f ~(a,b,c) = (a, b, f c)
+
+{-# INLINE zipWithTriple #-}
+zipWithTriple ::
+   (a -> d -> g, b -> e -> h, c -> f -> i) -> (a,b,c) -> (d,e,f) -> (g,h,i)
+zipWithTriple ~(g,h,i) ~(a,b,c) ~(d,e,f) = (g a d, h b e, i c f)
 
 {-# INLINE uncurry3 #-}
 uncurry3 :: (a -> b -> c -> d) -> ((a, b, c) -> d)
diff --git a/src/Data/Tuple/Strict.hs b/src/Data/Tuple/Strict.hs
--- a/src/Data/Tuple/Strict.hs
+++ b/src/Data/Tuple/Strict.hs
@@ -4,7 +4,7 @@
 
 {-# INLINE mapPair #-}
 mapPair :: (a -> c, b -> d) -> (a,b) -> (c,d)
-mapPair (f,g) (x,y) = (f x, g y)
+mapPair (f,g) (a,b) = (f a, g b)
 
 {-# INLINE mapFst #-}
 mapFst :: (a -> c) -> (a,b) -> (c,b)
@@ -14,17 +14,21 @@
 mapSnd :: (b -> c) -> (a,b) -> (a,c)
 mapSnd f (a,b) = (a, f b)
 
+{-# INLINE zipWithPair #-}
+zipWithPair :: (a -> c -> e, b -> d -> f) -> (a,b) -> (c,d) -> (e,f)
+zipWithPair (e,f) (a,b) (c,d) = (e a c, f b d)
 
+
 {-# INLINE swap #-}
 swap :: (a,b) -> (b,a)
-swap (x,y) = (y,x)
+swap (a,b) = (b,a)
 
 
 -- * Triple
 
 {-# INLINE mapTriple #-}
 mapTriple :: (a -> d, b -> e, c -> f) -> (a,b,c) -> (d,e,f)
-mapTriple (f,g,h) (x,y,z) = (f x, g y, h z)
+mapTriple (f,g,h) (a,b,c) = (f a, g b, h c)
 
 {-# INLINE mapFst3 #-}
 mapFst3 :: (a -> d) -> (a,b,c) -> (d,b,c)
@@ -37,6 +41,11 @@
 {-# INLINE mapThd3 #-}
 mapThd3 :: (c -> d) -> (a,b,c) -> (a,b,d)
 mapThd3 f (a,b,c) = (a, b, f c)
+
+{-# INLINE zipWithTriple #-}
+zipWithTriple ::
+   (a -> d -> g, b -> e -> h, c -> f -> i) -> (a,b,c) -> (d,e,f) -> (g,h,i)
+zipWithTriple (g,h,i) (a,b,c) (d,e,f) = (g a d, h b e, i c f)
 
 {-# INLINE uncurry3 #-}
 uncurry3 :: (a -> b -> c -> d) -> ((a, b, c) -> d)
diff --git a/src/Test.hs b/src/Test.hs
--- a/src/Test.hs
+++ b/src/Test.hs
@@ -1,5 +1,7 @@
 module Main where
 
+import qualified Test.Data.List.Reverse.StrictElement as RevElem
+import qualified Test.Data.List.Reverse.StrictSpine as RevSpine
 import qualified Test.Data.List      as ListHT
 import qualified Test.Data.ListMatch as ListMatch
 import qualified Test.Data.Maybe     as MaybeHT
@@ -14,6 +16,8 @@
 main =
    mapM_ (\(msg,io) -> putStr (msg++": ") >> io) $
    concat $
+      prefix "ReverseSpine" RevSpine.tests :
+      prefix "ReverseElem" RevElem.tests :
       prefix "List"      ListHT.tests :
       prefix "ListMatch" ListMatch.tests :
       prefix "Maybe"     MaybeHT.tests :
diff --git a/src/Test/Data/List.hs b/src/Test/Data/List.hs
--- a/src/Test/Data/List.hs
+++ b/src/Test/Data/List.hs
@@ -1,5 +1,6 @@
 module Test.Data.List where
 
+import qualified Data.List.Reverse.StrictElement as Rev
 import qualified Data.List.HT.Private as ListHT
 import qualified Data.List as List
 import Control.Monad (liftM2, )
@@ -11,13 +12,21 @@
 
 
 
-takeWhileRev :: (Ord a) => (a -> Bool) -> [a] -> Bool
-takeWhileRev p xs =
-   ListHT.takeWhileRev p xs == reverse (takeWhile p (reverse xs))
+takeWhileRev0 :: (Eq a) => (a -> Bool) -> [a] -> Bool
+takeWhileRev0 p xs =
+   ListHT.takeWhileRev0 p xs == Rev.takeWhile p xs
 
-dropWhileRev :: (Ord a) => (a -> Bool) -> [a] -> Bool
+takeWhileRev1 :: (Eq a) => (a -> Bool) -> [a] -> Bool
+takeWhileRev1 p xs =
+   ListHT.takeWhileRev1 p xs == Rev.takeWhile p xs
+
+takeWhileRev2 :: (Eq a) => (a -> Bool) -> [a] -> Bool
+takeWhileRev2 p xs =
+   ListHT.takeWhileRev2 p xs == Rev.takeWhile p xs
+
+dropWhileRev :: (Eq a) => (a -> Bool) -> [a] -> Bool
 dropWhileRev p xs =
-   ListHT.dropWhileRev p xs == reverse (dropWhile p (reverse xs))
+   ListHT.dropWhileRev p xs == Rev.dropWhile p xs
 
 
 takeRev :: (Eq a) => Int -> [a] -> Bool
@@ -28,7 +37,32 @@
 dropRev n xs =
    ListHT.dropRev n xs == reverse (drop n (reverse xs))
 
+splitAtRev :: (Eq a) => Int -> [a] -> Bool
+splitAtRev n xs =
+   xs == uncurry (++) (ListHT.splitAtRev n xs)
 
+
+breakAfterAppend :: (Eq a) => (a -> Bool) -> [a] -> Bool
+breakAfterAppend p xs =
+   uncurry (++) (ListHT.breakAfter p xs) == xs
+
+breakAfter0 :: (Eq a) => (a -> Bool) -> [a] -> Bool
+breakAfter0 p xs =
+   ListHT.breakAfterRec p xs == ListHT.breakAfterFoldr p xs
+
+breakAfter1 :: (Eq a) => (a -> Bool) -> [a] -> Bool
+breakAfter1 p xs =
+   ListHT.breakAfterRec p xs == ListHT.breakAfterBreak p xs
+
+breakAfter2 :: (Eq a) => (a -> Bool) -> [a] -> Bool
+breakAfter2 p xs =
+   ListHT.breakAfterRec p xs == ListHT.breakAfterTakeUntil p xs
+
+breakAfterUntil :: (Eq a) => (a -> Bool) -> [a] -> Bool
+breakAfterUntil p xs =
+   ListHT.takeUntil p xs == fst (ListHT.breakAfter p xs)
+
+
 sieve :: Eq a => Int -> [a] -> Property
 sieve n x =
    n>0 ==>
@@ -84,19 +118,36 @@
 mapAdjacent x xs =
    ListHT.mapAdjacent subtract (scanl (+) x xs) == xs
 
+mapAdjacentPointfree :: (Num a, Eq a) => [a] -> Bool
+mapAdjacentPointfree xs =
+   ListHT.mapAdjacent (+) xs == ListHT.mapAdjacentPointfree (+) xs
 
+
 simple ::
    (Testable test) =>
    (Int -> [Integer] -> test) -> IO ()
 simple = quickCheck
 
+elemCheck ::
+   (Testable test) =>
+   (Float -> [Float] -> test) -> IO ()
+elemCheck = quickCheck
 
+
 tests :: [(String, IO ())]
 tests =
-   ("takeWhileRev",     quickCheck (\a -> takeWhileRev ((a::Integer)>=))) :
-   ("dropWhileRev",     quickCheck (\a -> dropWhileRev ((a::Integer)>=))) :
+   ("takeWhileRev0",    elemCheck (\a -> takeWhileRev0 (a>=))) :
+   ("takeWhileRev1",    elemCheck (\a -> takeWhileRev1 (a>=))) :
+   ("takeWhileRev2",    elemCheck (\a -> takeWhileRev2 (a>=))) :
+   ("dropWhileRev",     elemCheck (\a -> dropWhileRev (a>=))) :
    ("takeRev",          simple takeRev) :
    ("dropRev",          simple dropRev) :
+   ("splitAtRev",       simple splitAtRev) :
+   ("breakAfterAppend", elemCheck (\a -> breakAfterAppend (a>=))) :
+   ("breakAfter0",      elemCheck (\a -> breakAfter0 (a>=))) :
+   ("breakAfter1",      elemCheck (\a -> breakAfter1 (a>=))) :
+   ("breakAfter2",      elemCheck (\a -> breakAfter2 (a>=))) :
+   ("breakAfterUntil",  elemCheck (\a -> breakAfterUntil (a>=))) :
    ("sieve",            simple sieve) :
    ("sliceHorizontal",  simple sliceHorizontal) :
    ("sliceVertical",    simple sliceVertical) :
@@ -105,4 +156,6 @@
    ("outerProduct",     quickCheck (outerProduct    :: [Integer] -> [Int] -> Bool)) :
    ("iterate",          quickCheck (iterate (+)     :: Integer -> Bool)) :
    ("mapAdjacent",      quickCheck (mapAdjacent     :: Integer -> [Integer] -> Bool)) :
+   ("mapAdjacentPointfree",
+                        quickCheck (mapAdjacentPointfree :: [Integer] -> Bool)) :
    []
diff --git a/src/Test/Data/List/Reverse/StrictElement.hs b/src/Test/Data/List/Reverse/StrictElement.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/Data/List/Reverse/StrictElement.hs
@@ -0,0 +1,53 @@
+module Test.Data.List.Reverse.StrictElement where
+
+import qualified Data.List.Reverse.StrictElement as Rev
+import qualified Data.List as List
+import Data.Tuple.HT (mapPair, swap, )
+
+import Test.QuickCheck (Testable, quickCheck, )
+
+import Prelude hiding (takeWhile, dropWhile, span, )
+
+
+takeWhile :: (Ord a) => (a -> Bool) -> [a] -> Bool
+takeWhile p xs =
+   Rev.takeWhile p xs == reverse (List.takeWhile p (reverse xs))
+
+dropWhile :: (Ord a) => (a -> Bool) -> [a] -> Bool
+dropWhile p xs =
+   Rev.dropWhile p xs == reverse (List.dropWhile p (reverse xs))
+
+span :: (Ord a) => (a -> Bool) -> [a] -> Bool
+span p xs =
+   Rev.span p xs == swap (mapPair (reverse, reverse) (List.span p (reverse xs)))
+
+spanTakeDrop :: (Ord a) => (a -> Bool) -> [a] -> Bool
+spanTakeDrop p xs =
+   Rev.span p xs == (Rev.dropWhile p xs, Rev.takeWhile p xs)
+
+dropWhileInf :: (Ord a) => a -> [a] -> Bool
+dropWhileInf x xs =
+   let ys = List.take 1000 $ Rev.dropWhile (x/=) $ cycle $ x:xs
+   in  ys==ys
+
+spanInf :: (Ord a) => a -> [a] -> Bool
+spanInf x xs =
+   let ys = List.take 1000 $ fst $ Rev.span (x/=) $ cycle $ x:xs
+   in  ys==ys
+
+
+simple ::
+   (Testable test) =>
+   (Float -> [Float] -> test) -> IO ()
+simple = quickCheck
+
+
+tests :: [(String, IO ())]
+tests =
+   ("takeWhile",     simple (\a -> takeWhile (a>=))) :
+   ("dropWhile",     simple (\a -> dropWhile (a>=))) :
+   ("span",          simple (\a -> span (a>=))) :
+   ("spanTakeDrop",  simple (\a -> spanTakeDrop (a>=))) :
+   ("dropWhileInf",  simple dropWhileInf) :
+   ("spanInf",       simple spanInf) :
+   []
diff --git a/src/Test/Data/List/Reverse/StrictSpine.hs b/src/Test/Data/List/Reverse/StrictSpine.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/Data/List/Reverse/StrictSpine.hs
@@ -0,0 +1,62 @@
+module Test.Data.List.Reverse.StrictSpine where
+
+import qualified Data.List.Reverse.StrictSpine as Rev
+import qualified Data.List.Match as Match
+import qualified Data.List as List
+import Data.Tuple.HT (mapFst, mapPair, swap, )
+
+import Test.QuickCheck (Testable, quickCheck, )
+
+import Prelude hiding (takeWhile, dropWhile, span, )
+
+
+takeWhile :: (Ord a) => (a -> Bool) -> [a] -> Bool
+takeWhile p xs =
+   Rev.takeWhile p xs == reverse (List.takeWhile p (reverse xs))
+
+dropWhile :: (Ord a) => (a -> Bool) -> [a] -> Bool
+dropWhile p xs =
+   Rev.dropWhile p xs == reverse (List.dropWhile p (reverse xs))
+
+span :: (Ord a) => (a -> Bool) -> [a] -> Bool
+span p xs =
+   Rev.span p xs == swap (mapPair (reverse, reverse) (List.span p (reverse xs)))
+
+spanTakeDrop :: (Ord a) => (a -> Bool) -> [a] -> Bool
+spanTakeDrop p xs =
+   Rev.span p xs == (Rev.dropWhile p xs, Rev.takeWhile p xs)
+
+takeWhileBottom :: (Ord a) => a -> [a] -> [a] -> Bool
+takeWhileBottom x xs pad =
+   let ys = Rev.takeWhile (x/=) $ Match.replicate pad undefined ++ x:xs
+   in  ys==ys
+
+dropWhileBottom :: (Ord a) => a -> [a] -> [a] -> Bool
+dropWhileBottom x xs pad =
+   let n = length $ Rev.dropWhile (x/=) $ Match.replicate pad undefined ++ x:xs
+   in  n==n
+
+spanBottom :: (Ord a) => a -> [a] -> [a] -> Bool
+spanBottom x xs pad =
+   let (n,ys) =
+          mapFst length $ Rev.span (x/=) $
+          Match.replicate pad undefined ++ x:xs
+   in  n==n && ys==ys
+
+
+simple ::
+   (Testable test) =>
+   (Float -> [Float] -> test) -> IO ()
+simple = quickCheck
+
+
+tests :: [(String, IO ())]
+tests =
+   ("takeWhile",     simple (\a -> takeWhile (a>=))) :
+   ("dropWhile",     simple (\a -> dropWhile (a>=))) :
+   ("span",          simple (\a -> span (a>=))) :
+   ("spanTakeDrop",  simple (\a -> spanTakeDrop (a>=))) :
+   ("takeWhileBottom", simple takeWhileBottom) :
+   ("dropWhileBottom", simple dropWhileBottom) :
+   ("spanBottom", simple spanBottom) :
+   []
diff --git a/utility-ht.cabal b/utility-ht.cabal
--- a/utility-ht.cabal
+++ b/utility-ht.cabal
@@ -1,5 +1,5 @@
 Name:             utility-ht
-Version:          0.0.11
+Version:          0.0.12
 License:          BSD3
 License-File:     LICENSE
 Author:           Henning Thielemann <haskell@henning-thielemann.de>
@@ -27,6 +27,7 @@
 Tested-With:       GHC==7.0.2, GHC==7.2.2, GHC==7.4.1, GHC==7.8.2
 Cabal-Version:     >=1.10
 Build-Type:        Simple
+Stability:         Stable
 
 -- workaround for Cabal-1.10
 Extra-Source-Files:
@@ -44,7 +45,7 @@
 Source-Repository this
   type:     darcs
   location: http://code.haskell.org/~thielema/utility/
-  tag:      0.0.11
+  tag:      0.0.12
 
 Library
   Build-Depends:
@@ -54,6 +55,7 @@
   GHC-Options:      -Wall
   Hs-Source-Dirs:   src
   Exposed-Modules:
+    Data.Bits.HT
     Data.Bool.HT
     Data.Eq.HT
     Data.Function.HT
@@ -61,6 +63,8 @@
     Data.List.HT
     Data.List.Key
     Data.List.Match
+    Data.List.Reverse.StrictElement
+    Data.List.Reverse.StrictSpine
     Data.Maybe.HT
     Data.Monoid.HT
     Data.Ord.HT
@@ -70,6 +74,7 @@
     Data.Tuple.Lazy
     Data.Tuple.Strict
     Control.Monad.HT
+    Control.Applicative.HT
     Control.Functor.HT
     Data.Strictness.HT
     Text.Read.HT
@@ -96,6 +101,8 @@
   Other-Modules:
     Test.Data.List
     Test.Data.ListMatch
+    Test.Data.List.Reverse.StrictElement
+    Test.Data.List.Reverse.StrictSpine
     Test.Data.Maybe
     Test.Data.Function
     Test.Utility
