diff --git a/keera-hails-reactivevalues.cabal b/keera-hails-reactivevalues.cabal
--- a/keera-hails-reactivevalues.cabal
+++ b/keera-hails-reactivevalues.cabal
@@ -7,7 +7,7 @@
 -- The package version. See the Haskell package versioning policy
 -- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for
 -- standards guiding when and how versions should be incremented.
-Version:             0.2.0.2
+Version:             0.2.2.0
 
 -- A short (one-line) description of the package.
 Synopsis:            Haskell on Rails - Reactive Values
diff --git a/src/Control/GFunctor.hs b/src/Control/GFunctor.hs
--- a/src/Control/GFunctor.hs
+++ b/src/Control/GFunctor.hs
@@ -1,23 +1,28 @@
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE FlexibleInstances     #-}
--- {-# LANGUAGE RankNTypes           #-}
--- {-# LANGUAGE TypeSynonymInstances #-}
--- Functors parameterised over the morphisms in the source category
+-- | Functors parameterised over the morphisms in the source category.
 module Control.GFunctor where
 
 infixl 8 <$$>
 
 -- class ContravariantFunctor f where
 --   cmap :: (b -> a) -> f a -> f b
--- 
+--
 
+-- | A class for Functors in which the morphisms in the source category do not
+-- have to be of kind arrow '(->)', but can be anything (see the parameter
+-- 'm').
 class GFunctor f m where
+  -- | Map parameterised over the morphisms in the source category.
   gmap :: m a b -> f a -> f b
- 
+
+-- | Trivial instance for the arrow morphism '(->)'. Anything
+-- that is a functor is also a GFunctor in the trivial way.
 instance (Functor a) => GFunctor a (->) where
   gmap = fmap
 
-(<$$>) :: GFunctor f m =>m a b -> f a -> f b
+-- | A more readable (ignorable) name for 'gmap'.
+(<$$>) :: GFunctor f m => m a b -> f a -> f b
 (<$$>) = gmap
 
 -- class GFunctor f m => GApplicative f m where
diff --git a/src/Data/ReactiveValue.hs b/src/Data/ReactiveValue.hs
--- a/src/Data/ReactiveValue.hs
+++ b/src/Data/ReactiveValue.hs
@@ -1,48 +1,259 @@
 {-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FunctionalDependencies #-}
 {-# LANGUAGE FlexibleContexts #-}
--- | Reactive Values are typed mutable variables with a change notification
--- mechanism.
+-- | Reactive Values (RVs) are typed mutable variables with a change
+-- notification mechanism.
 --
 -- They are defined by providing a way to read the value, a way to change it,
 -- and a way to install an event listener when the value has changed.
 --
--- RVs are pruposely defined in an abstract way, as a type class. GUI toolkits,
+-- RVs are pruposely abstract, defined as a type class. GUI toolkits,
 -- for instance, can use existing event-handling installing mechanisms to
 -- enclose widget attributes as Reactive Values, without the need for an
--- extra layer.
+-- additional, manually-handled event dispatcher.
 --
--- RVs are complemented with Relation-building functions, which
--- enable pairing RVs during execution so that they are kept in
--- sync for the duration of the program.
+-- RVs are complemented with /relation-building/ functions, which
+-- enable pairing RVs during execution so that they are /kept in/
+-- /sync/ for the duration of the program.
 --
 -- This module only defines RVs and operations on them. For connections
 -- to existing backends (GUIs, devices, files, network, FRP), see
 -- https://github.com/keera-studios/keera-hails
 --
-module Data.ReactiveValue where
+module Data.ReactiveValue
+  ( -- * Reactive Values
 
+    -- ** Readable Reactive Values
+    -- $readablervs
+    ReactiveValueRead(..)
+
+    -- ** Writable Reactive Values
+
+    -- $writablervs
+  , ReactiveValueWrite(..)
+
+    -- ** Read-Write Reactive Values
+
+    -- $readwritervs
+  , ReactiveValueReadWrite
+
+    -- * Reactive Relations or Rules
+
+    -- $rules
+  , (=:>)
+  , (=:=)
+  , (<:=)
+
+    -- * Activatable Reactive Values
+
+    -- $activatable
+  , ReactiveFieldActivatable
+  , ReactiveValueActivatable(..)
+  , mkActivatable
+
+    -- * Purely functional implementation of RVs.
+
+    -- $fields
+  , ReactiveFieldRead(..)
+  , ReactiveFieldWrite(..)
+  , ReactiveFieldReadWrite(..)
+
+    -- ** Setters, getters and notifiers
+
+    -- $settersgetters
+  , FieldGetter
+  , FieldSetter
+  , FieldNotifier
+
+    -- * RV combinators
+
+    -- ** Creating, lifting on and manipulating readable values
+
+    -- $readablecombinators
+  , constR
+  , initRW
+  , liftR
+  , (<^>)
+  , liftR2
+  , liftR3
+  , liftMR
+  , readOnly
+  , wrapMR
+  , wrapMRPassive
+  , eventR
+
+    -- *** Merging
+  , lMerge
+  , rMerge
+
+    -- ** Creating, lifting on and manipulating writeable values
+
+    -- $writablecombinators
+  , constW
+  , liftW
+  , liftW2
+  , (&.&)
+  , liftMW
+  , writeOnly
+  , wrapMW
+  , wrapDo
+  , wrapDo_
+
+
+    -- ** Lift monadic actions/sinks (setters) and sources (getters)
+
+    -- *** Lifting (sink) computations into writable RVs.
+
+    -- $readwritecombinators
+
+    -- **** Bijective functions
+  , BijectiveFunc
+  , bijection
+  , direct
+  , inverse
+  , Involution
+  , involution
+
+    -- **** Combinators
+  , liftRW
+  , liftRW2
+  , pairRW
+  , modRW
+  , reactiveValueModify
+
+
+    -- * Stopping change
+
+    -- $changecontrol
+
+    -- ** Stopping unnecesary change propagation
+  , eqCheck
+
+    -- ** Stopping all change propagation
+  , passivelyR
+  , passivelyRW
+
+    -- ** Changing control over change propagation
+  , governingR
+  , governingRW
+
+    -- ** Conditional change propagation
+  , ifRW
+  , ifRW_
+  , guardRO
+  , guardRO'
+  )
+ where
+
 import Control.Monad
 import Control.GFunctor -- Functors parameterised over the morphisms
                         -- in the source category
 import Data.Functor.Contravariant
 
--- * Reactive values: common interface for all RVs
+-- $readablervs
+--
+-- Readable reactive values are mutable values that can be read and, possibly,
+-- trigger notifications when they change.
+--
+-- RVs without event handling are considered /passive/. That is their default
+-- behaviour if 'reactiveValueOnCanRead' is not specialised.
+-- BEWARE: Active and passive RVs are not differentiated at the type level.
+--
+-- You are responsible of installing any potential thread-safety
+-- mechanisms when you implement instances, and to ensure that operations
+-- are executed in the right thread (some GUI toolkits may require that).
+-- It is important that the way that ensured that monadic actions are
+-- executed in the right thread can be nested; otherwise, some propagation can
+-- block.
 
--- | Readable reactive values
-class ReactiveValueRead a b m | a -> b, a -> m where
+-- | A class for all Readable RVs. They can be read-only or read-write.
+--
+-- If your type is also writeable (a writable RV or simply if it is not
+-- constant), you can include a change handler installer here. By default
+-- no change handlers are installed.
+--
+-- Use a monad with "error" if reading or installing a handler can fail.
+class Monad m => ReactiveValueRead a b m | a -> b, a -> m where
+
+  -- | Install a handler that will be executed when the reactive value
+  -- changes.
   reactiveValueOnCanRead :: a -> m () -> m ()
+  reactiveValueOnCanRead _ _ = return ()
+
+  -- | Provide the last known value for this reactive value.
   reactiveValueRead :: a -> m b
 
--- | Writable reactive values
+  {-# MINIMAL reactiveValueRead #-}
+
+-- | Monadic actions are readable, but they do not provide any
+-- change notification.
+instance ReactiveValueRead (IO a) a IO where
+  -- | Executes the monadic action and provides a value.
+  reactiveValueRead = id
+
+-- | Pairs carrying a monadic action as their first component are Readable RVs.
+instance (Functor m, Monad m) => ReactiveValueRead (m a, a -> m b) a m where
+  reactiveValueRead = fst
+
+-- $writablervs
+--
+-- Writable reactive values are those that we can write to.
+-- They behave like sinks: there are no guarantees that anything happens,
+-- or result codes.
+--
+-- You are responsible of installing any potential thread-safety
+-- mechanisms when you implement instances, and to ensure that operations
+-- are executed in the right thread (some GUI toolkits may require that).
+-- It is important that the way that ensured that monadic actions are
+-- executed in the right thread can be nested; otherwise, some propagation can
+-- block.
+
+-- | A minimal type class for all mutable values. Use a monad with error
+-- if changing the value can fail.
 class ReactiveValueWrite a b m | a -> b, a -> m where
   reactiveValueWrite :: a -> b -> m ()
 
--- | Read-write reactive values
+-- | Monadic actions are trivially writable RVs in that monad, by ignoring the
+-- argument and executing the action. This is particularly suitable for IO code
+-- that just runs an action when a given value changes.
+instance ReactiveValueWrite (IO a) () IO where
+  reactiveValueWrite m _ = void m
+
+-- | Monadic actions parameterised over an input are trivially writable RVs in
+-- that monad. This is particularly suitable for IO code that just runs an
+-- action when a given value changes, using that value.
+instance (Functor m, Monad m) => ReactiveValueWrite (a -> m b) a m where
+  reactiveValueWrite f v = void (f v)
+
+-- | To facilitate creating RW reactive values from monadic actions, pairs
+-- of a getter and a setter are also RVs.
+instance ReactiveValueWrite (a -> m b) a m => ReactiveValueWrite (m a, a -> m b) a m where
+  reactiveValueWrite (_, f) v = reactiveValueWrite f v
+
+-- $readwritervs
+--
+-- RVs can be readable and writable, which is useful to create bi-directional
+-- rules (combinators like '(=:=)' require this instance).
+--
+
+-- | Read-write Reactive Values are trivially defined. This class only captures
+-- the constraints of both the other classes. There is no need to implement
+-- any methods.
 class (ReactiveValueRead a b m, ReactiveValueWrite a b m) => ReactiveValueReadWrite a b m
 
--- * Reactive rules (data dependency/passing building combinators)
+-- | Pairs of a monadic action and a parametric monadic action are also RVs
+instance (Functor m, Monad m) => ReactiveValueReadWrite (m a, a -> m b) a m
 
--- | Priorities so that we can write them infix without parenthesising
+-- $rules
+--
+-- Reactive Rules are data dependency (data-passing) building combinators.
+-- By executing them, you install the right event handlers on the right RVs, so
+-- that values pass to the other RV.
+--
+-- Reactive Relations cannot be independently removed. If the event-dispatching
+-- is handled internally by RVs, and two connected RVs are removed, then the
+-- rules should also disappear with them.
+
+-- Priorities so that we can write them infix without parenthesising
 infix 9 =:=
 infix 9 =:>
 infix 9 <:=
@@ -72,60 +283,90 @@
   -- where sync1 = reactiveValueRead v1 >>= reactiveValueWrite v2
   --       sync2 = reactiveValueRead v2 >>= reactiveValueWrite v1
 
--- * Purely functional implementation of RVs.
+-- $settersgetters
 --
 -- These are used internally for combinators that need to return RV instances. They can
 -- also be used to write new backends and library extensions, but they are not
 -- recommended to enclose application models. For that purpose, see light models and
 -- protected models instead.
 
--- ** Setters, getters and notifiers
+-- | The type of a monadic value producer (a getter, a source).
 type FieldGetter m a   = m a
+
+-- | The type of a monadic value consumer (a setter, a sink, a slot).
 type FieldSetter m a   = a -> m ()
+
+-- | The type of an event handler installer
 type FieldNotifier m a = m () -> m () -- FIXME: why does fieldnotifier have an argument
 
--- ** Concrete types implementing the above interface
-data ReactiveFieldRead      m a = ReactiveFieldRead (FieldGetter m a) (FieldNotifier m a)
-data ReactiveFieldWrite     m a = ReactiveFieldWrite (FieldSetter m a)
-data ReactiveFieldReadWrite m a = ReactiveFieldReadWrite (FieldSetter m a) (FieldGetter m a) (FieldNotifier m a)
+-- $fields
+-- This is a specific implementation of RVs that does not have a custom event queue.
+--
+-- It can be used to return RVs in the combinators, by relying on the underlying
+-- change detection and event notification system (underlying meaning or the RV
+-- that these were created from).
 
-instance ReactiveValueRead (ReactiveFieldRead m a) a m where
+-- | A Read-Only RV.
+data ReactiveFieldRead m a =
+  ReactiveFieldRead (FieldGetter m a) (FieldNotifier m a)
+
+-- | A Write-Only RV.
+data ReactiveFieldWrite m a =
+  ReactiveFieldWrite (FieldSetter m a)
+
+-- | A Read-Write RV.
+data ReactiveFieldReadWrite m a =
+  ReactiveFieldReadWrite (FieldSetter m a) (FieldGetter m a) (FieldNotifier m a)
+
+instance Monad m => ReactiveValueRead (ReactiveFieldRead m a) a m where
   reactiveValueOnCanRead (ReactiveFieldRead _ notifier) = notifier
   reactiveValueRead (ReactiveFieldRead getter _)        = getter
 
-instance ReactiveValueWrite (ReactiveFieldWrite m a) a m where
+instance Monad m => ReactiveValueWrite (ReactiveFieldWrite m a) a m where
   reactiveValueWrite (ReactiveFieldWrite setter) = setter
 
-instance ReactiveValueRead (ReactiveFieldReadWrite m a) a m where
+instance Monad m => ReactiveValueRead (ReactiveFieldReadWrite m a) a m where
   reactiveValueOnCanRead (ReactiveFieldReadWrite _ _ notifier) = notifier
   reactiveValueRead (ReactiveFieldReadWrite _ getter _)        = getter
 
-instance ReactiveValueWrite (ReactiveFieldReadWrite m a) a m where
+instance Monad m => ReactiveValueWrite (ReactiveFieldReadWrite m a) a m where
   reactiveValueWrite (ReactiveFieldReadWrite setter _ _) = setter
 
-instance ReactiveValueReadWrite (ReactiveFieldReadWrite m a) a m
+instance Monad m => ReactiveValueReadWrite (ReactiveFieldReadWrite m a) a m
 
--- ** Activatable reactive values (producing units)
+-- $activatable
+--
+-- Activatable RVs are values that never hold any data, but whose change (or
+-- activation, or some sort of internal event) we need to be aware of).
+
+-- | A class for things with a trivial field that carries unit. Buttons
+-- (in any GUI library), for instance, could be a member of this class.
+class ReactiveValueActivatable m a where
+   defaultActivation :: a -> ReactiveFieldActivatable m
+
+-- | A trivial type for Readable RVs that carry unit. They can be used for
+-- buttons, or events without data.
 type ReactiveFieldActivatable m = ReactiveFieldRead m ()
 
+-- | Create an activatable RV from a handler installer.
 mkActivatable :: Monad m => (m () -> m ()) -> ReactiveFieldActivatable m
 mkActivatable f = ReactiveFieldRead getter notifier
  where getter   = return ()
        notifier = f
 
-class ReactiveValueActivatable m a where
-   defaultActivation :: a -> ReactiveFieldActivatable m
-
 -- instance (ReactiveValueWrite a b) => ReactiveValueWrite (TypedReactiveValue a b) b where
 --   reactiveValueWrite (TypedReactiveValue x _) v = reactiveValueWrite x v
--- 
+--
 -- instance (ReactiveValueRead a b) => ReactiveValueRead (TypedReactiveValue a b) b where
 --   reactiveValueOnCanRead (TypedReactiveValue x _) v op = (reactiveValueOnCanRead x) v op
 --   reactiveValueRead (TypedReactiveValue x _)           = reactiveValueRead x
 
--- * Creating RVs based on other RVs
+-- $readablecombinators
 
--- ** Lifting onto readable values
+-- | A trivial RV builder tith a constant value. We need this because
+-- we cannot have overlapping instances with a default case, and because
+-- the interpretation of lifting with RVs could be very confusing unless
+-- values are lifted into RVs explicitly.
 constR :: Monad m => a ->  ReactiveFieldRead m a
 constR e = ReactiveFieldRead getter notifier
  where notifier _ = return ()
@@ -137,8 +378,6 @@
  where notifier _ = return ()
        getter     = return e
 
--- ** Lifting onto readable values
-
 -- | Lift a transformation onto a RV. Note that this creates a new
 -- RV, it does not modify the existing RV.
 liftR :: (Monad m, ReactiveValueRead a b m) => (b -> c) -> a -> ReactiveFieldRead m c
@@ -185,8 +424,31 @@
  where notifier = reactiveValueOnCanRead e
        getter   = f =<< reactiveValueRead e
 
--- ** Lifting onto writeable values
+-- *** Lifting (source) computations into readable RVs.
 
+{-# ANN wrapMR "HLint: ignore Eta reduce" #-}
+-- | Wrap an reading operation and an notification installer in
+-- a readable reactive value.
+wrapMR :: m a -> (m () -> m ()) -> ReactiveFieldRead m a
+wrapMR f p = ReactiveFieldRead f p
+
+-- | Wrap an reading operation into an RV. Because there is
+-- no way to detect changes, the resulting RV is passive (does
+-- not push updates).
+wrapMRPassive :: Monad m => m a -> ReactiveFieldRead m a
+wrapMRPassive f = ReactiveFieldRead f (const (return ()))
+
+{-# ANN eventR "HLint: ignore Eta reduce" #-}
+-- | Wrap event-handler installers in RVs
+eventR :: Monad m => (m () -> m ()) -> ReactiveFieldRead m ()
+eventR notifInstaller = ReactiveFieldRead (return ()) notifInstaller
+
+-- | Make a RW RV read only
+readOnly :: ReactiveValueRead r a m => r -> ReactiveFieldRead m a
+readOnly r = ReactiveFieldRead (reactiveValueRead r) (reactiveValueOnCanRead r)
+
+-- $writablecombinators
+
 -- | Create a constant writable RV.
 --
 constW :: (Monad m, ReactiveValueWrite v a m) => a -> v -> ReactiveFieldWrite m b
@@ -227,17 +489,11 @@
 liftMW f e = ReactiveFieldWrite setter
   where setter x = reactiveValueWrite e =<< f x
 
--- | Make a RW RV read only
-readOnly :: ReactiveValueRead r a m => r -> ReactiveFieldRead m a
-readOnly r = ReactiveFieldRead (reactiveValueRead r) (reactiveValueOnCanRead r)
-
 -- | Make a RW RV write only
 writeOnly :: ReactiveValueWrite r a m => r -> ReactiveFieldWrite m a
 writeOnly r = ReactiveFieldWrite (reactiveValueWrite r)
 
--- ** Lift monadic actions/sinks (setters) and sources (getters)
-
--- *** Lifting (sink) computations into writable RVs.
+-- $readwritecombinators
 
 -- | Wrap a monadic computation in a writable reactive value.
 wrapMW :: (a -> m ()) -> ReactiveFieldWrite m a
@@ -249,6 +505,10 @@
 -- Note: Because the value is discarded, the resulting RV is
 -- polymorphic in the value that may be written to it. Using
 -- 'wrapDo_' may save you some extra type signatures.
+--
+-- NOTE: this should be unnecessary since the introduction
+-- of a default 'ReactiveValueWrite' instance for monadic
+-- actions.
 wrapDo :: m () -> ReactiveFieldWrite m a
 wrapDo = wrapMW . const
 
@@ -257,59 +517,48 @@
 wrapDo_ :: m () -> ReactiveFieldWrite m ()
 wrapDo_ = wrapDo
 
--- *** Lifting (source) computations into readable RVs.
-
-{-# ANN wrapMR "HLint: ignore Eta reduce" #-}
--- | Wrap an reading operation and an notification installer in
--- a readable reactive value.
-wrapMR :: m a -> (m () -> m ()) -> ReactiveFieldRead m a
-wrapMR f p = ReactiveFieldRead f p
-
--- | Wrap an reading operation into an RV. Because there is
--- no way to detect changes, the resulting RV is passive (does
--- not push updates).
-wrapMRPassive :: Monad m => m a -> ReactiveFieldRead m a
-wrapMRPassive f = ReactiveFieldRead f (const (return ()))
-
-{-# ANN eventR "HLint: ignore Eta reduce" #-}
--- | Wrap event-handler installers in RVs
-eventR :: Monad m => (m () -> m ()) -> ReactiveFieldRead m ()
-eventR notifInstaller = ReactiveFieldRead (return ()) notifInstaller
-
--- ** Lifting onto read-write values
+-- Lifting onto read-write values
 
--- *** Bijections
+-- | Bijections
 newtype BijectiveFunc a b = BijectiveFunc
   { unBijectiveFunc :: (a -> b, b -> a) }
 
+-- | Create a bijection ('BijectiveFunc') from a couple of functions
 bijection :: (a -> b, b -> a) -> BijectiveFunc a b
 bijection = BijectiveFunc
 
 {-# ANN direct "HLint: ignore Redundant bracket" #-}
+-- | Obtain the direct function from a bijection
 direct :: BijectiveFunc a b -> (a -> b)
 direct = fst . unBijectiveFunc
 
 {-# ANN inverse "HLint: ignore Redundant bracket" #-}
+-- | Obtain the inverse function from a bijection
 inverse :: BijectiveFunc a b -> (b -> a)
 inverse = snd . unBijectiveFunc
 
+-- | Involutions (functions that are the same as their inverse)
 type Involution a = BijectiveFunc a a
+
+-- | Create an involution from a function
 involution :: (a -> a) -> Involution a
 involution f = BijectiveFunc (f, f)
 
--- *** Actual lifting
+-- | Lift a bijection onto a read-write RV
 liftRW :: (Monad m, ReactiveValueReadWrite a b m)
        => BijectiveFunc b c -> a -> ReactiveFieldReadWrite m c
 liftRW (BijectiveFunc (f1, f2)) e = ReactiveFieldReadWrite setter getter notifier
   where ReactiveFieldRead getter notifier = liftR f1 e
         ReactiveFieldWrite setter         = liftW f2 e
 
+-- | Lift a bijection onto two read-write RVs
 liftRW2 :: (Monad m, ReactiveValueReadWrite a b m, ReactiveValueReadWrite c d m)
         => BijectiveFunc e (b,d) -> a -> c -> ReactiveFieldReadWrite m e
 liftRW2 (BijectiveFunc (f1, f2)) e1 e2 = ReactiveFieldReadWrite setter getter notifier
   where ReactiveFieldRead getter notifier = liftR2 (curry f2) e1 e2
         ReactiveFieldWrite setter         = liftW2 f1 e1 e2
 
+-- | Pair two read-write RVs
 pairRW :: (Monad m,
            ReactiveValueReadWrite a b m,
            ReactiveValueReadWrite c d m)
@@ -317,15 +566,18 @@
        -> ReactiveFieldReadWrite m (b, d)
 pairRW = liftRW2 (bijection (id, id))
 
+-- | Add an equality check to the setter of a Read-Write RV, effectively stopping
+-- all unnecessary change (the RV is not modified if it has not changed).
 {-# INLINE eqCheck #-}
 eqCheck :: (Eq v, Monad m) => ReactiveFieldReadWrite m v -> ReactiveFieldReadWrite m v
 eqCheck (ReactiveFieldReadWrite setter getter notifier) = ReactiveFieldReadWrite setter' getter notifier
  where setter' v = do o <- getter
                       when (o /= v) $ setter v
 
--- ** Modifying reactive values (applying modification transformations)
 
--- | Lifting modification functions
+-- | Lift a function that takes an old value and a new input and creates a new
+-- value. It is similar to how fold works: the RV represents the accumulator,
+-- and the values are provided in succession by writing to the resulting RV.
 modRW :: (Monad m, ReactiveValueReadWrite a b m)
       => (b -> c -> b) -> a -> ReactiveFieldWrite m c
 modRW f rv = ReactiveFieldWrite setter
@@ -333,11 +585,12 @@
                       let b' = f b c
                       reactiveValueWrite rv b'
 
+-- | Apply a modification to an RV. This modification is not attached to
+-- the RV, and there are no guarantees that it will be atomic (if you need
+-- atomicity, check out STM.
 reactiveValueModify :: (Monad m, ReactiveValueReadWrite a b m) => a -> (b -> b) -> m ()
 reactiveValueModify r f = reactiveValueWrite r . f =<< reactiveValueRead r
 
--- * Merging
-
 {-# ANN lMerge "HLint: ignore Use const" #-}
 -- | Left merge (give priority to the value on the left)
 lMerge :: (Monad m, ReactiveValueRead a v m, ReactiveValueRead b v m)
@@ -349,19 +602,31 @@
        => a -> b -> ReactiveFieldRead m v
 rMerge = liftR2 (\_ b -> b)
 
--- * Deactivating reactive values
+-- $changecontrol
+--
+-- Sometimes you need to create complex liftings between RVs in which
+-- only changes to one of them should provoke change propagation.
+-- These combinators allow you to stop propagation (making RVs passive),
+-- make one RV control the change propagation of another (governance),
+-- filter propagation based on some condition (guards) and have a
+-- boolean-carrying RV guard another.
 
--- | Turning an active RV into a passive one (does not propagate changes)
+-- Turning an active RV into a passive one (does not propagate changes)
 -- Note that this does not really affect the RV itself, only produces a new
 -- RV that will not propagate changes. So, if used in a reactive relation,
 -- values will not get propagated when they change. It is useful in combination
 -- with lifts, to achieve things similar to Yampa's tagging, but this might
 -- be more general.
+
+-- | Create a passive RO RV backed by another Readable RV by disabling change
+-- propagation.
 passivelyR :: (Monad m, ReactiveValueRead a b m)
            => a -> ReactiveFieldRead m b
 passivelyR rv =
   ReactiveFieldRead (reactiveValueRead rv) (\_ -> return ())
 
+-- | Create a passive RW RV backed by another RW RV by disabling change
+-- propagation.
 passivelyRW :: (Monad m, ReactiveValueReadWrite a b m)
             => a -> ReactiveFieldReadWrite m b
 passivelyRW rv =
@@ -378,31 +643,23 @@
   where getter   = reactiveValueRead c
         notifier = reactiveValueOnCanRead r
 
--- * Conditionals
-
--- Check condition and notify only when holds
-ifRW_ :: (Monad m, ReactiveValueRead c Bool m, ReactiveValueReadWrite v a m)
-      => c -> v
-      -> ReactiveFieldReadWrite m a
-ifRW_ c r = ReactiveFieldReadWrite setter getter notifier
-  where setter = reactiveValueWrite r
-        getter = reactiveValueRead r
-        -- If either changes, the value *may* be propagated
-        notifier p = do reactiveValueOnCanRead c (when' p)
-                        reactiveValueOnCanRead r (when' p)
+-- | A form of binary read-writable lifting that passifies the second RV but reads
+-- exclusively from it.
 
-        -- Propagate only if the condition holds
-         where when' m = do x <- reactiveValueRead c
-                            when x m
+governingRW :: (ReactiveValueRead a b m,  ReactiveValueReadWrite c d m)
+           => a -> c -> ReactiveFieldReadWrite m d
+governingRW r c = ReactiveFieldReadWrite setter getter notifier
+  where getter   = reactiveValueRead c
+        setter   = reactiveValueWrite c
+        notifier = reactiveValueOnCanRead r
 
--- Check condition, and write or notify only when it holds
+-- | Check condition, and write or notify only when it holds.
 ifRW :: (Monad m, ReactiveValueRead c Bool m, ReactiveValueReadWrite v a m)
      => c -> v
      -> ReactiveFieldReadWrite m a
 ifRW c r = ReactiveFieldReadWrite setter getter notifier
   where setter x   = do b <- reactiveValueRead c
-                        when b $
-                          reactiveValueWrite r x
+                        when b $ reactiveValueWrite r x
         getter     = reactiveValueRead r
         -- If either changes, the value *may* be propagated
         notifier p = do reactiveValueOnCanRead c (when' p)
@@ -412,7 +669,24 @@
          where when' m = do b <- reactiveValueRead c
                             when b m
 
--- Check condition and notify only when holds
+-- | Check condition and notify only when holds (but writing occurs
+-- regardless).
+ifRW_ :: (Monad m, ReactiveValueRead c Bool m, ReactiveValueReadWrite v a m)
+      => c -> v
+      -> ReactiveFieldReadWrite m a
+ifRW_ c r = ReactiveFieldReadWrite setter getter notifier
+  where setter = reactiveValueWrite r
+        getter = reactiveValueRead r
+        -- If either changes, the value *may* be propagated
+        notifier p = do reactiveValueOnCanRead c (when' p)
+                        reactiveValueOnCanRead r (when' p)
+
+        -- Propagate only if the condition holds
+         where when' m = do x <- reactiveValueRead c
+                            when x m
+
+-- | Check RV carrying a 'Bool', and notify only when it changes and it is
+-- 'True'.
 guardRO :: (Monad m, ReactiveValueRead c Bool m)
         => c
         -> ReactiveFieldRead m Bool
@@ -425,7 +699,9 @@
          where when' m = do x <- reactiveValueRead c
                             when x m
 
--- Check condition and notify only when holds
+-- | Check RV and notify only when condition on the value holds.
+--
+-- (stops propagation by filtering on the new value).
 guardRO' :: (Monad m, ReactiveValueRead c a m)
          => c
          -> (a -> Bool)
diff --git a/tests/HaddockCoverage.hs b/tests/HaddockCoverage.hs
--- a/tests/HaddockCoverage.hs
+++ b/tests/HaddockCoverage.hs
@@ -7,7 +7,7 @@
 -- Stability   :  provisional
 -- Portability :  portable
 --
--- Copyright notice: This file borrows code 
+-- Copyright notice: This file borrows code
 -- https://hackage.haskell.org/package/lens-4.7/src/tests/doctests.hsc
 -- which is itself licensed BSD-style as well.
 --
@@ -16,6 +16,7 @@
 -----------------------------------------------------------------------------
 module Main where
 
+import Control.Applicative
 import Control.Monad
 import Data.List
 import System.Directory
@@ -38,14 +39,7 @@
   -- https://github.com/haskell/haddock/issues/309#issuecomment-150811929
   files <- getSources
 
-  -- Run haddock in the right sandbox.
-  -- NOTE: you need this version of haddock:
-  -- https://github.com/keera-studios/haddock/
-  --
-  -- TODO: adapt to use even the old version of haddock if the modified one is
-  -- not present. We can test with haddock --csv-coverage and no input
-  -- and check the exit code.
-  let haddockArgs = [ "--csv-coverage", "--no-warnings" ] ++ files
+  let haddockArgs = [ "--no-warnings" ] ++ files
   let cabalArgs   = [ "exec", "--", "haddock" ] ++ haddockArgs
   (code, out, _err) <- readProcessWithExitCode "cabal" cabalArgs ""
 
@@ -91,4 +85,4 @@
 -- find-based implementation (not portable)
 --
 -- getSources :: IO [FilePath]
--- getSources = fmap lines $ readProcess "find" ["src/", "-iname", "*hs"] "" 
+-- getSources = fmap lines $ readProcess "find" ["src/", "-iname", "*hs"] ""
diff --git a/tests/Tasty.hs b/tests/Tasty.hs
--- a/tests/Tasty.hs
+++ b/tests/Tasty.hs
@@ -38,7 +38,7 @@
 
 -- | Check that constR returns the value put in.
 getOnConst :: Int -> Bool
-getOnConst = 
+getOnConst =
   \val -> let rv   = constR (val :: Int)
               val' = runIdentity (reactiveValueRead rv)
           in val == val'
