diff --git a/Data/Record/Label.hs b/Data/Record/Label.hs
--- a/Data/Record/Label.hs
+++ b/Data/Record/Label.hs
@@ -11,28 +11,30 @@
   , mkModifier
   , mkLabel
 
-  -- * Bidirectional composition.
-
+  -- * Identity and composition.
+  , idL
   , (%)
+
+  -- * Bidirectional functor.
+
   , Lens (..)
+  , (%%)
 
   -- * State monadic label operations.
 
   , getM, setM, modM, (=:)
-  , enterM
-  , enterMT
-  , bothM
-  , localM
-  , withM
 
-  -- * Convenient label for list indexing.
+  -- * Useful example labels.
   , list
+  , maybeNull
 
   -- * Derive labels using Template Haskell.
   , module Data.Record.Label.TH
 
   ) where
 
+import Prelude hiding ((.), id)
+import Control.Category
 import Control.Monad.State
 import Data.Record.Label.TH
 
@@ -57,10 +59,17 @@
 mkLabel :: Getter a b -> Setter a b -> a :-> b
 mkLabel g s = Label g s (mkModifier g s)
 
+idL :: a :-> a
+idL = mkLabel id const
+
 infixr 8 %
 (%) :: (g :-> a) -> (f :-> g) -> (f :-> a)
 a % b = Label (lget a . lget b) (lmod b . lset a) (lmod b . lmod a)
 
+instance Category (:->) where
+  id = idL
+  (.) = (%)
+
 -- Apply custom `parser' and 'printer' function. This can be seen as a
 -- bidirectional functorial map.
 
@@ -70,8 +79,12 @@
 instance Lens ((:->) f) where
   lmap (f, g) (Label a b c) = Label (f . a) (b . g) (c . (g.) . (.f))
 
--- Extend the state monad with support for labels.
+-- | Apply label to lifted value and join afterwards.
 
+infixr 8 %%
+(%%) :: Functor f => a :-> b -> g :-> f a -> g :-> f b
+(%%) a b = let (Label g s _) = a in (fmap g, fmap (\k -> s k (error "unused"))) `lmap` b
+
 -- | Get a value out of state pointed to by the specified label.
 
 getM :: MonadState s m => s :-> b -> m b
@@ -94,46 +107,13 @@
 modM :: MonadState s m => s :-> b -> (b -> b) -> m ()
 modM l = modify . lmod l
 
-
-
-
-
--- Run a state computation for a sub element updating this part of the state afterwards.
-
-enterM :: MonadState s m => s :-> b -> State b b1 -> m b1
-enterM l c = do
-  b <- getM l
-  let (a, s) = runState c b
-  setM l s
-  return a
-
-enterMT
-  :: (MonadState s (t m), MonadTrans t, Monad m)
-  => s :-> b -> StateT b m a -> t m a
-enterMT l c = do
-  b <- getM l
-  (a, s) <- lift $ runStateT c b
-  setM l s
-  return a
-
-bothM :: MonadState s m => s :-> b -> State b b1 -> m (b, b1)
-bothM parent cmp = do
-  p <- getM parent
-  c <- enterM parent cmp
-  return (p, c)
-
-localM :: MonadState s m => s :-> b -> m b1 -> m b1
-localM l comp = do
-  k <- getM l
-  c <- comp
-  setM l k
-  return c
-
-withM :: MonadState s m => s :-> b -> State b a -> m b1 -> m b1
-withM l c d = localM l (enterM l c >> d)
-
 -- Lift list indexing to a label.
 
 list :: Int -> [a] :-> a
 list i = mkLabel (!! i) (\v a -> take i a ++ [v] ++ drop (i+1) a)
+
+-- View null lists as Nothing.
+
+maybeNull :: [a] :-> Maybe [a]
+maybeNull = (\x -> if null x then Nothing else Just x, maybe [] id) `lmap` id
 
diff --git a/fclabels.cabal b/fclabels.cabal
--- a/fclabels.cabal
+++ b/fclabels.cabal
@@ -1,19 +1,22 @@
-name:            fclabels
-version:         0.2.0
-author:          Sebastiaan Visser, Erik Hesselink
-synopsis:        First class record labels
-description:     First class labels for records, with combinators, allowing
-                 selection, modification and update inside (nested) records.
-                 Also includes MonadState versions of these, and template
-                 haskell generation of the labels.
-maintainer:      Sebastiaan Visser <sfvisser@cs.uu.nl>
-license:         BSD3
-license-file:    LICENCE
-category:        Data
-build-type:      Simple
-cabal-version:   >= 1.6
-exposed-modules: Data.Record.Label
-other-modules:   Data.Record.Label.TH
-
-build-depends:   base >= 3 && < 5, template-haskell >= 2.2 && < 2.4, monads-fd ==0.0.*
+Name:            fclabels
+Version:         0.3.0
+Author:          Sebastiaan Visser, Erik Hesselink
+Synopsis:        First class accessor labels.
+Description:     First class labels that act as bidirectional records fields.
+                 The labels are fully composable and can be used to get, set
+                 and modify part of datatypes in a consistent way. The label
+                 datatype, conveniently called `:->', is an instance of the
+                 `Category' type class, so is has a proper identity and
+                 composition. The library has support for automatically
+                 deriving labels from record selectors that start with an
+                 underscore.
+Maintainer:      Sebastiaan Visser <sfvisser@cs.uu.nl>
+License:         BSD3
+License-File:    LICENCE
+Category:        Data
+Build-Type:      Simple
+Cabal-Version:   >= 1.6
+Exposed-Modules: Data.Record.Label
+Other-Modules:   Data.Record.Label.TH
+Build-Depends:   base >= 3 && < 5, template-haskell >= 2.2 && < 2.4, monads-fd ==0.0.*
 
