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
@@ -1,20 +1,37 @@
 module Control.Monad.HT where
 
+import Control.Monad (liftM, liftM2, )
+import Prelude hiding (repeat, until, )
+
+{- |
+Monadic 'List.repeat'.
+-}
+repeat :: (Monad m) => m a -> m [a]
+repeat x =
+   let go = liftM2 (:) x go in go
+
+{-# DEPRECATED untilM "use M.until" #-}
 {- | repeat action until result fulfills condition -}
-untilM :: (Monad m) => (a -> Bool) -> m a -> m a
-untilM p m =
-   do x <- m
-      if p x
-        then return x
-        else untilM p m
+until, untilM :: (Monad m) => (a -> Bool) -> m a -> m a
+untilM = until
+until p m =
+   let go =
+         do x <- m
+            if p x
+              then return x
+              else go
+   in  go
 
--- parameter order equal to that of 'nest'
-iterateLimitM :: Monad m => Int -> (a -> m a) -> a -> m [a]
-iterateLimitM m f =
-   let aux 0 x = return [x]
-       aux n x = do y <- f x
-                    z <- aux (n-1) y
-                    return (x : z)
+{-# DEPRECATED iterateLimitM "use M.iterateLimit" #-}
+{- | parameter order equal to that of 'nest' -}
+iterateLimit, iterateLimitM :: Monad m => Int -> (a -> m a) -> a -> m [a]
+iterateLimitM = iterateLimit
+iterateLimit m f =
+   let aux n x =
+          liftM (x:) $
+          if n==0
+            then return []
+            else aux (n-1) =<< f x
    in  aux m
 
 {- |
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
@@ -229,6 +229,7 @@
    flip seq True . (!!100) . concat . segmentBefore p . cycle . (x:)
 
 
+-- cf. Matroid.hs
 {- |
 @removeEach xs@ represents a list of sublists of @xs@,
 where each element of @xs@ is removed and
diff --git a/src/Data/Record/HT.hs b/src/Data/Record/HT.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Record/HT.hs
@@ -0,0 +1,6 @@
+module Data.Record.HT (
+   R.compare,
+   R.equal,
+   ) where
+
+import qualified Data.Record.HT.Private as R
diff --git a/src/Data/Record/HT/Private.hs b/src/Data/Record/HT/Private.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Record/HT/Private.hs
@@ -0,0 +1,37 @@
+module Data.Record.HT.Private where
+
+import Data.Monoid (mconcat, )
+import Data.List.HT (switchL, )
+
+{- |
+Lexicographically compare a list of attributes of two records.
+
+Example:
+
+> compare [comparing fst, comparing snd]
+-}
+{-# INLINE compare #-}
+compare :: [a -> a -> Ordering] -> a -> a -> Ordering
+compare cs x y =
+   mconcat $ map (\c -> c x y) cs
+
+{-# INLINE compare1 #-}
+compare1 :: [a -> a -> Ordering] -> a -> a -> Ordering
+compare1 cs x y =
+   switchL EQ const $ dropWhile (EQ==) $ map (\c -> c x y) cs
+
+{-# INLINE compare2 #-}
+compare2 :: [a -> a -> Ordering] -> a -> a -> Ordering
+compare2 cs x y =
+   head $ dropWhile (EQ==) (map (\c -> c x y) cs) ++ [EQ]
+
+{- |
+Check whether a selected set of fields of two records is equal.
+
+Example:
+
+> equal [equating fst, equating snd]
+-}
+{-# INLINE equal #-}
+equal :: [a -> a -> Bool] -> a -> a -> Bool
+equal cs x y = all (\c -> c x y) cs
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.2
+Version:          0.0.3
 License:          BSD3
 License-File:     LICENSE
 Author:           Henning Thielemann <haskell@henning-thielemann.de>
@@ -27,7 +27,7 @@
 Source-Repository this
   type:     darcs
   location: http://code.haskell.org/~thielema/utility/
-  tag:      0.0.2
+  tag:      0.0.3
 
 
 Library
@@ -44,6 +44,7 @@
     Data.List.Match
     Data.Maybe.HT
     Data.Ord.HT
+    Data.Record.HT
     Data.Tuple.HT
     Control.Monad.HT
     Text.Read.HT
@@ -54,3 +55,4 @@
     Data.List.Key.Private
     Data.List.Match.Private
     Data.Function.HT.Private
+    Data.Record.HT.Private
