diff --git a/Control/LVish.hs b/Control/LVish.hs
--- a/Control/LVish.hs
+++ b/Control/LVish.hs
@@ -10,6 +10,7 @@
 {-# LANGUAGE DataKinds #-}  -- For 'Determinism'
 -- {-# LANGUAGE ConstraintKinds, KindSignatures #-}
 {-# LANGUAGE MagicHash #-}
+{-# LANGUAGE BangPatterns #-}
 {-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
 
 {-|
@@ -17,14 +18,15 @@
   The @lvish@ package provides a parallel programming model based on monotonically
   growing data structures.
 
-  This module provides the core scheduler and basic control flow operations.  
-  But to do anything useful you will need to import one of the data structure modules
-  (@Data.LVar.*@).
+  This module provides the core scheduler and basic control flow
+  operations.  But to do anything useful you will need to import, along
+  with this module, one of the data structure modules (@Data.LVar.*@).
 
-  Here is a self-contained example that writes the same value to @num@
-  twice and deterministically prints @4@ instead of raising an error, as
-  it would if @num@ were a traditional IVar rather than an LVar. (You
-  will need to compile using the @-XDataKinds@ extension.)
+  Here is a self-contained example. This program writes the same value
+  to an @LVar@ called @num@ twice.  It deterministically prints @4@
+  instead of raising an error, as it would if @num@ were a traditional
+  IVar rather than an LVar. (You will need to compile using the
+  @-XDataKinds@ extension.)
 
 > {-# LANGUAGE DataKinds #-}
 > import Control.LVish  -- Generic scheduler; works with any lattice.
@@ -53,7 +55,7 @@
     guaranteed-deterministic.  Unfortunately, as of this release there is still one back-door
     that hasn't yet been closed.
 
-    If an adverserial user defines invalid `Eq` instances (claiming objects are equal when they're
+    If an adversarial user defines invalid `Eq` instances (claiming objects are equal when they're
     not), or if they define a `compare` function that is not a /pure, total function/,
     and then they store those types within `LVar`s,
     then nondeterminism may leak out of a parallel `runPar` computation.
@@ -160,7 +162,7 @@
 withNewPool_ f = WrapPar $ L.withNewPool_ $ unWrapPar . f
 
 -- | If the input computation is quasi-deterministic (`QuasiDet`), then this may
--- throw a `LVishException` non-deterministically on the thread that calls it, but if
+-- throw a `LVishException` nondeterministically on the thread that calls it, but if
 -- it returns without exception then it always returns the same answer.
 --
 -- If the input computation is deterministic (`Det`), then @runParIO@ will return the
@@ -168,7 +170,7 @@
 -- avoiding an extra `unsafePerformIO` required inside the implementation of
 -- `runPar`.
 -- 
--- In the future, /full/ non-determinism may be allowed as a third setting beyond
+-- In the future, /full/ nondeterminism may be allowed as a third setting beyond
 -- `Det` and `QuasiDet`.
 runParIO :: (forall s . Par d s a) -> IO a
 runParIO (WrapPar p) = L.runParIO p 
@@ -262,3 +264,14 @@
              (halfT,remT) = tiles `quotRem` 2
          fork$ loop offset half halfT
          loop (offset+half) (half+rem) (halfT+remT)
+
+
+-- | A simple for loop for numeric ranges (not requiring deforestation
+-- optimizations like `forM`).  Inclusive start, exclusive end.
+{-# INLINE for_ #-}
+for_ :: Monad m => (Int, Int) -> (Int -> m ()) -> m ()
+for_ (start, end) _fn | start > end = error "for_: start is greater than end"
+for_ (start, end) fn = loop start
+  where
+  loop !i | i == end  = return ()
+          | otherwise = do fn i; loop (i+1)
diff --git a/Control/LVish/DeepFrz.hs b/Control/LVish/DeepFrz.hs
--- a/Control/LVish/DeepFrz.hs
+++ b/Control/LVish/DeepFrz.hs
@@ -8,13 +8,15 @@
 
 {-|
 
-Provides a way to return arbitrarily complex data-structures containing LVars
-from `Par` computations.
+The `DeepFrz` module rovides a way to return arbitrarily complex data
+structures containing LVars from `Par` computations.
 
-The important thing to know is that to use `runParThenFreeze` you must make sure that
-all types you return from the parallel computation have `DeepFrz` instances.  This
-means if you introduce custom (non-LVar) datatypes, you will need to include a bit of
-boilerplate to give them `DeepFrz` instances.  Here is a complete example:
+The important thing to know is that to use `runParThenFreeze` to run a
+`Par` computation, you must make sure that all types you return from
+the `Par` computation have `DeepFrz` instances.  This means that, if
+you wish to return a user-defined type, you will need to include a bit
+of boilerplate to give it a `DeepFrz` instance.  Here is a complete
+example:
 
 > {-# LANGUAGE TypeFamilies #-}
 > import Control.LVish.DeepFrz
@@ -28,7 +30,9 @@
 
 -}
 
--- LK: TODO: another example of a recursive FrzType would be nice.
+-- TODO: a more detailed (recursive?) DeepFrz instance example might
+-- be really helpful here for people who want to implement their own
+-- LVar types. -- LK
 
 module Control.LVish.DeepFrz
        (
@@ -52,30 +56,35 @@
 import Control.LVish.SchedIdempotent (runPar, runParIO)
 --------------------------------------------------------------------------------
 
--- | Under normal conditions, calling a `freeze` operation makes a `Par` computation
--- quasi-deterministic.  However, if we freeze once all LVar operations are completed
--- (after the implicit global barrier of `runPar`), then we've avoided all data
--- races, and freezing is therefore safe.
+-- | Under normal conditions, calling a `freeze` operation inside a
+-- `Par` computation makes the `Par` computation quasi-deterministic.
+-- However, if we freeze only after all LVar operations are completed
+-- (after the implicit global barrier of `runPar`), then we've avoided
+-- all data races, and freezing is therefore safe.  Running a `Par`
+-- computation with `runParThenFreeze` accomplishes this, without our
+-- having to call `freeze` explicitly.
 -- 
--- For this to be possible, the type returned from the `Par` computation must be a
--- member of the `DeepFrz` class.  All LVar libraries should provide this instance
--- already.  Further, you can create additional instances for custom, pure datatypes.
--- The result of a `runParThenFreeze` depends on the type-level function `FrzType`,
--- whose only purpose is to toggle the `s` parameters of all IVars to the `Frzn`
--- state.
---
+-- In order to use `runParThenFreeze`, the type returned from the
+-- `Par` computation must be a member of the `DeepFrz` class.  All the
+-- @Data.LVar.*@ libraries should provide instances of `DeepFrz`
+-- already.  Further, you can create additional instances for custom,
+-- pure datatypes.  The result of a `runParThenFreeze` depends on the
+-- type-level function `FrzType`, whose only purpose is to toggle the
+-- `s` parameters of all IVars to the `Frzn` state.
+-- 
 -- Significantly, the freeze at the end of `runParThenFreeze` has /no/ runtime cost, in
 -- spite of the fact that it enables a /deep/ (recursive) freeze of the value returned
 -- by the `Par` computation.
 runParThenFreeze :: DeepFrz a => Par Det s a -> FrzType a
 runParThenFreeze (WrapPar p) = frz $ runPar p
 
--- | This version works for non-deterministic computations as well.
+-- | This version works for nondeterministic computations as well.
 -- 
--- Such computations may also do freezes internally, but this function has an
--- advantage vs. doing your own freeze at the end of your computation.  Namely, when
--- you use `runParThenFreezeIO`, there is an implicit barrier before the final
--- freeze.  Further, `DeepFrz` has no runtime overhead, whereas regular freezing has a cost.
+-- Of course, nondeterministic computations may also call `freeze`
+-- internally, but this function has an advantage to doing your own
+-- `freeze` at the end of a `runParIO`: there is an implicit barrier
+-- before the final freeze.  Further, `DeepFrz` has no runtime
+-- overhead, whereas regular freezing has a cost.
 runParThenFreezeIO :: DeepFrz a => Par d s a -> IO (FrzType a)
 runParThenFreezeIO (WrapPar p) = do
   x <- runParIO p
diff --git a/Control/LVish/DeepFrz/Internal.hs b/Control/LVish/DeepFrz/Internal.hs
--- a/Control/LVish/DeepFrz/Internal.hs
+++ b/Control/LVish/DeepFrz/Internal.hs
@@ -3,7 +3,7 @@
 {-# LANGUAGE DefaultSignatures #-}
 {-# LANGUAGE EmptyDataDecls #-}
 
--- | This module is NOT Safe-Haskell, but it must be used to create
+-- | This module is /not/ Safe Haskell, but it must be used to create
 -- new LVar types.
 module Control.LVish.DeepFrz.Internal
        (
@@ -11,11 +11,13 @@
        )
        where
 
--- | DeepFreezing is type-level (guaranteed O(1) time complexity)
+-- | DeepFreezing is a type-level (guaranteed O(1) time complexity)
 -- operation.  It marks an LVar and its contents (recursively) as
 -- frozen.  DeepFreezing is not an action that can be taken directly
--- by the user, however.  Rather it is an optional final-step in a
--- `runPar` invocation.
+-- by the user, however.  Rather, it is the final step in a
+-- `runParThenFreeze` invocation.
+
+-- An instance of DeepFrz is a valid return valud for `runParThenFreeze`
 class DeepFrz a where
   -- | This type function is public.  It maps pre-frozen types to
   -- frozen ones.  It should be idempotent.
@@ -30,12 +32,12 @@
   default frz :: a -> a 
   frz a = a 
 
--- | An uninhabited type that signals an LVar has been frozen.
---   LVars should use this inplace of their `s` parameter.
+-- | An uninhabited type that signals that an LVar has been frozen.
+-- LVars should use this in place of their `s` parameter.
 data Frzn
 
--- | An uninhabited type that signals an LVar is not only frozen, but
--- it may be traversed in whatever order its internal representation
--- dictates.
+-- | An uninhabited type that signals that an LVar is not only frozen,
+-- but it may be traversed in whatever order its internal
+-- representation dictates.
 data Trvrsbl 
 
diff --git a/Control/LVish/Internal.hs b/Control/LVish/Internal.hs
--- a/Control/LVish/Internal.hs
+++ b/Control/LVish/Internal.hs
@@ -1,17 +1,17 @@
 {-# LANGUAGE Unsafe #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE GADTs #-}
-{-# LANGUAGE BangPatterns  #-}
 {-# LANGUAGE DataKinds #-}  -- For Determinism
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE KindSignatures #-}
 
 {-|
 
-This module is note @SafeHaskell@; as an end-user, you shouldn't ever need to import it.
+This module is /not/ Safe Haskell; as an end-user, you shouldn't ever
+need to import it.
 
-It is exposed only because it is necessary for writing /new/ LVars that live in their
-own, separate packages.
+It is exposed only because it is necessary for implementing /new/ LVar
+types that will live in their own, separate packages.
 
 -}
 
@@ -20,14 +20,13 @@
     -- * Type-safe wrappers around internal components
     Par(..), LVar(..),
     Determinism(..),
+    QPar,
     
     -- * Unsafe conversions and lifting
     unWrapPar, unsafeRunPar,
     unsafeConvert, state,
-    liftIO,
+    liftIO
 
-    -- * General utilities
-    for_
   )
   where
 
@@ -61,6 +60,9 @@
   WrapPar :: L.Par a -> Par d s a
   deriving (Monad, Functor, Applicative)
 
+-- | A shorthand for quasi-deterministic `Par` computations.
+type QPar = Par QuasiDet
+
 -- | The generic representation of LVars used by the scheduler.  The
 -- end-user can't actually do anything with these and should not try
 -- to.
@@ -90,14 +92,3 @@
 
 instance MonadToss (Par d s) where
   toss = WrapPar L.toss
-
--- | A simple for loop for numeric ranges (not requiring deforestation
--- optimizations like `forM`).  Inclusive start, exclusive end.
-{-# INLINE for_ #-}
-for_ :: Monad m => (Int, Int) -> (Int -> m ()) -> m ()
-for_ (start, end) _fn | start > end = error "for_: start is greater than end"
-for_ (start, end) fn = loop start
-  where
-  loop !i | i == end  = return ()
-          | otherwise = do fn i; loop (i+1)
-  
diff --git a/Control/LVish/SchedIdempotent.hs b/Control/LVish/SchedIdempotent.hs
--- a/Control/LVish/SchedIdempotent.hs
+++ b/Control/LVish/SchedIdempotent.hs
@@ -16,27 +16,27 @@
 {-# OPTIONS_GHC -Wall -fno-warn-name-shadowing -fno-warn-unused-do-bind #-}
 
 -- | This is an internal module that provides the core parallel scheduler.
---   It is NOT for end-users.
+--   It is /not/ for end-users.
 
 module Control.LVish.SchedIdempotent
   (
-    -- * Basic types and accessors:
+    -- * Basic types and accessors
     LVar(), state, HandlerPool(),
     Par(..), ClosedPar(..),
     
-    -- * Safe, deterministic operations:
+    -- * Safe, deterministic operations
     yield, newPool, fork, forkHP,
     runPar, runParIO, runParLogged,
     withNewPool, withNewPool_,
     forkWithExceptions,
     
-    -- * Quasi-deterministic operations:
+    -- * Quasi-deterministic operations
     quiesce, quiesceAll,
 
     -- * Debug facilities
     logStrLn, dbgLvl,
        
-    -- * UNSAFE operations.  Should be used only by experts to build new abstractions.
+    -- * Unsafe operations; should be used only by experts to build new abstractions
     newLV, getLV, putLV, putLV_, freezeLV, freezeLVAfter,
     addHandler, liftIO, toss
   ) where
@@ -96,7 +96,7 @@
 {-# INLINE logStrLn_ #-}
 #endif
 
--- | Print all accumulated log lines
+-- | Print all accumulated log lines.
 printLog :: IO ()
 printLog = do
   -- Clear the log when we read it:
@@ -131,7 +131,7 @@
 
 {-# NOINLINE dbgLvl #-}
 -- | Debugging flag shared by several modules.
---   This is activated by setting the environment variable DEBUG=1..5
+--   This is activated by setting the environment variable @DEBUG=1..5@.
 dbgLvl :: Int
 dbgLvl = case lookup "DEBUG" theEnv of
        Nothing  -> defaultDbg
@@ -151,20 +151,20 @@
 
 -- | LVars are parameterized by two types:
 -- 
---     * The first, @a@, characterizes the "state" of the LVar (i.e. the lattice
---     value), and should be a concurrently mutable data type.  That means, in
---     particular, that only a /transient snapshot/ of the lattice value can be
+--     * The first, @a@, characterizes the \"state\" of the LVar (i.e., the lattice
+--     element), and should be a concurrently mutable data type.  That means, in
+--     particular, that only a /transient snapshot/ of the state can be
 --     obtained in general.  But the information in such a snapshot is always a
 --     lower bound on the current value of the LVar.
---
---     * The second, @d@, characterizes the "delta" associated with a @putLV@
---     operation (i.e. the actual change, if any, to the LVar's lattice value).
+-- 
+--     * The second, @d@, characterizes the \"delta\" associated with a @putLV@
+--     operation (i.e., the actual change, if any, to the LVar's state).
 --     In many cases such deltas allow far more efficient communication between
 --     @putLV@s and blocked @getLV@s or handlers.  It is crucial, however, that
 --     the behavior of a @get@ or handler does not depend on the /particular/
 --     choice of @putLV@ operations (and hence deltas) that moved the LVar over
 --     the threshold.  For simple data structures, the delta may just be the
---     entire LVar state, but for e.g. collection data structures, delta will
+--     entire LVar state, but for, e.g., collection data structures, delta will
 --     generally represent a single insertion.
 data LVar a d = LVar {
   state  :: a,                -- the current, "global" state of the LVar
@@ -189,7 +189,7 @@
   = Frozen                       -- further changes to the state are forbidden
   | Active (B.Bag (Listener d))  -- bag of blocked threshold reads and handlers
 
--- | A listener for an LVar is informed of each change to the LVar's lattice value
+-- | A listener for an LVar is informed of each change to the LVar's state
 -- (represented as a delta) and the event of the LVar freezing.  The listener is
 -- given access to a bag token, allowing it to remove itself from the bag of
 -- listeners, after unblocking a threshold read, for example.  It is also given
@@ -200,9 +200,9 @@
   onFreeze ::      B.Token (Listener d) -> SchedState -> IO ()
 }
 
--- | A HandlerPool contains a way to count outstanding parallel computations that
+-- | A @HandlerPool@ contains a way to count outstanding parallel computations that
 -- are affiliated with the pool.  It detects the condition where all such threads
--- have completeed.
+-- have completed.
 data HandlerPool = HandlerPool {
   numHandlers      :: C.Counter,   -- How many handler callbacks are currently
                                    -- running?
@@ -260,7 +260,7 @@
 -- LVar operations
 ------------------------------------------------------------------------------
     
--- | Create an LVar
+-- | Create an LVar.
 newLV :: IO a -> Par (LVar a d)
 newLV init = mkPar $ \k q -> do
   state     <- init
@@ -272,7 +272,7 @@
 -- | Do a threshold read on an LVar
 getLV :: (LVar a d)                  -- ^ the LVar 
       -> (a -> Bool -> IO (Maybe b)) -- ^ already past threshold?
-      -> (d ->         IO (Maybe b)) -- ^ does d pass the threshold?
+      -> (d ->         IO (Maybe b)) -- ^ does @d@ pass the threshold?
       -> Par b
 getLV lv@(LVar {state, status}) globalThresh deltaThresh = mkPar $ \k q -> do
   -- tradeoff: we fastpath the case where the LVar is already beyond the
@@ -333,9 +333,9 @@
             Nothing -> sched q
 
 
--- | Update an LVar
+-- | Update an LVar.
 putLV_ :: LVar a d                 -- ^ the LVar
-       -> (a -> Par (Maybe d, b))  -- ^ how to do the put and whether the LVar's
+       -> (a -> Par (Maybe d, b))  -- ^ how to do the put, and whether the LVar's
                                    -- value changed
        -> Par b
 putLV_ LVar {state, status, name} doPut = mkPar $ \k q -> do  
@@ -359,8 +359,8 @@
 putLV lv doPut = putLV_ lv doPut'
   where doPut' a = do r <- liftIO (doPut a); return (r, ())
 
--- | Freeze an LVar (limited nondeterminism)
---   It is the data-structure implementors responsibility to expose this as qasi-deterministc.
+-- | Freeze an LVar (introducing quasi-determinism).
+--   It is the data structure implementor's responsibility to expose this as quasi-deterministc.
 freezeLV :: LVar a d -> Par ()
 freezeLV LVar {name, status} = mkPar $ \k q -> do
   oldStatus <- atomicModifyIORef status $ \s -> (Frozen, s)    
@@ -376,7 +376,7 @@
 -- Handler pool operations
 ------------------------------------------------------------------------------  
 
--- | Create a handler pool
+-- | Create a handler pool.
 newPool :: Par HandlerPool
 newPool = mkPar $ \k q -> do
   cnt <- C.new
@@ -385,15 +385,15 @@
   hpMsg " [dbg-lvish] Created new pool" hp
   exec (k hp) q
   
--- | Convenience function.  Execute a Par computation in the context of a fresh handler pool
+-- | Convenience function.  Execute a @Par@ computation in the context of a fresh handler pool.
 withNewPool :: (HandlerPool -> Par a) -> Par (a, HandlerPool)
 withNewPool f = do
   hp <- newPool
   a  <- f hp
   return (a, hp)
   
--- | Convenience function.  Execute a Par computation in the context of a fresh
--- handler pool, while ignoring the result of the computation
+-- | Convenience function.  Execute a @Par@ computation in the context of a fresh
+-- handler pool, while ignoring the result of the computation.
 withNewPool_ :: (HandlerPool -> Par ()) -> Par HandlerPool
 withNewPool_ f = do
   hp <- newPool
@@ -402,7 +402,7 @@
 
 data DecStatus = HasDec | HasNotDec
 
--- | Close a Par task so that it is properly registered with a handler pool
+-- | Close a @Par@ task so that it is properly registered with a handler pool.
 closeInPool :: Maybe HandlerPool -> Par () -> IO ClosedPar
 closeInPool Nothing c = return $ close c $ const (ClosedPar sched)
 closeInPool (Just hp) c = do
@@ -437,7 +437,7 @@
                                     -- continuation that clears it from the
                                     -- handler pool
 
--- | Add a handler to an existing pool
+-- | Add a handler to an existing pool.
 {-# INLINE addHandler #-}
 addHandler :: Maybe HandlerPool           -- ^ pool to enroll in, if any
            -> LVar a d                    -- ^ LVar to listen to
@@ -462,7 +462,7 @@
                                       -- launch any callbacks now
     exec (k ()) q 
 
--- | Block until a handler pool is quiescent      
+-- | Block until a handler pool is quiescent.
 quiesce :: HandlerPool -> Par ()
 quiesce hp@(HandlerPool cnt bag) = mkPar $ \k q -> do
   hpMsg " [dbg-lvish] Begin quiescing pool, identity= " hp
@@ -485,8 +485,9 @@
   logStrLn_ " [dbg-lvish] Return from global barrier."
   exec (k ()) q
 
--- | Freeze an LVar after a given handler quiesces
---   This is quasideterministic, but it 
+-- | Freeze an LVar after a given handler quiesces.
+
+-- This is quasi-deterministic.
 freezeLVAfter :: LVar a d                    -- ^ the LVar of interest
               -> (a -> IO (Maybe (Par ())))  -- ^ initial callback
               -> (d -> IO (Maybe (Par ())))  -- ^ subsequent callbacks: updates
@@ -505,7 +506,7 @@
 -- Par monad operations
 ------------------------------------------------------------------------------
 
--- | Fork a child thread, optionally in the context of a handler pool
+-- | Fork a child thread, optionally in the context of a handler pool.
 forkHP :: Maybe HandlerPool -> Par () -> Par ()
 forkHP mh child = mkPar $ \k q -> do
   closed <- closeInPool mh child
@@ -513,11 +514,11 @@
 --  hpMsg " [dbg-lvish] incremented and pushed work in forkInPool, now running cont" hp   
   exec closed q  
   
--- | Fork a child thread
+-- | Fork a child thread.
 fork :: Par () -> Par ()
 fork f = forkHP Nothing f
 
--- | Perform an IO action
+-- | Perform an @IO@ action.
 liftIO :: IO a -> Par a
 liftIO io = mkPar $ \k q -> do
   r <- io
@@ -531,7 +532,7 @@
     writeIORef (Sched.prng q) g'
     exec (k b) q
 
--- | Cooperatively schedule other threads
+-- | Cooperatively schedule other threads.
 yield :: Par ()  
 yield = mkPar $ \k q -> do
   Sched.yieldWork q (k ())
@@ -642,7 +643,7 @@
 runParIO :: Par a -> IO a
 runParIO = runPar_internal
 
--- | Debugging aide.  Return debugging logs, in realtime order, in addition to the
+-- | Debugging aid.  Return debugging logs, in realtime order, in addition to the
 -- final result.
 runParLogged :: Par a -> IO ([String],a)
 runParLogged c =
@@ -677,7 +678,7 @@
            " transient cnt "++show c
 
 
--- | Exceptions that walk up the fork tree of threads:
+-- | Exceptions that walk up the fork tree of threads.
 forkWithExceptions :: (IO () -> IO ThreadId) -> String -> IO () -> IO ThreadId
 forkWithExceptions forkit descr action = do 
    parent <- myThreadId
diff --git a/Data/LVar/Generic.hs b/Data/LVar/Generic.hs
--- a/Data/LVar/Generic.hs
+++ b/Data/LVar/Generic.hs
@@ -3,11 +3,11 @@
 {-# LANGUAGE KindSignatures #-}
 {-# LANGUAGE DataKinds #-}  -- For Determinism
 
--- | A generic interface providing operations that work on ALL LVars.
+-- | A generic interface providing operations that work on /all/ LVars.
 
 module Data.LVar.Generic
        (
-         -- * The classes containing the generic interfaces
+         -- * Classes containing the generic interfaces
          LVarData1(..), OrderedLVarData1(..),
          
          -- * Supporting types and utilities
@@ -26,14 +26,14 @@
 
 --------------------------------------------------------------------------------
 
--- |/Some LVar datatypes are stored in an /internally/ ordered way so
+-- | Some LVar datatypes are stored in an /internally/ ordered way so
 -- that it is then possible to take /O(1)/ frozen snapshots and consume them
 -- inexpensively in a deterministic order.
---
+-- 
 -- LVars with this additional property provide this class as well as `LVarData1`.
 class LVarData1 f => OrderedLVarData1 (f :: * -> * -> *) where
   -- | Don't just freeze the LVar, but make the full contents
-  -- completely available and Foldable.  Guaranteed /O(1)/.
+  -- completely available and `Foldable`.  Guaranteed /O(1)/.
   snapFreeze :: f s a -> Par QuasiDet s (f Trvrsbl a)
 
 {- 
@@ -52,13 +52,13 @@
 -- Dealing with frozen LVars.
 ------------------------------------------------------------------------------
 
--- | `Trvrsbl` is a stronger property than `Frzn` so it is always ok to \"upcast\" to
+-- | `Trvrsbl` is a stronger property than `Frzn`, so it is always safe to \"upcast\" to
 -- the weaker version.
 castFrzn :: LVarData1 f => f Trvrsbl a -> f Frzn a
 castFrzn x = unsafeCoerceLVar x
 
--- | LVish Par actions must commute, therefore one safe way to consume a frozen (but
--- unordered) LVar, /even in another runPar session/, is to run a par computation for
+-- | LVish `Par` actions must commute, therefore one safe way to consume a frozen (but
+-- unordered) LVar, /even in another `runPar` session/, is to run a `Par` computation for
 -- each element.
 forFrzn :: LVarData1 f => f Frzn a -> (a -> Par d s ()) -> Par d s ()
 forFrzn fzn fn =
diff --git a/Data/LVar/Generic/Internal.hs b/Data/LVar/Generic/Internal.hs
--- a/Data/LVar/Generic/Internal.hs
+++ b/Data/LVar/Generic/Internal.hs
@@ -29,9 +29,9 @@
 -- Interface for generic LVar handling
 ------------------------------------------------------------------------------
 
--- | A class representing monotonic data types that take one type
--- parameter as well as an `s` parameter for session safety.
---
+-- | A class representing monotonic data structures that take /one/ type
+-- parameter, as well as an `s` parameter for session safety.
+-- 
 -- LVars that fall into this class are typically collection types.
 class (F.Foldable (f Trvrsbl)) => LVarData1 (f :: * -> * -> *)
      --   TODO: if there is a Par class to generalize LVar Par monads, then
@@ -46,9 +46,9 @@
 
   -- | An /O(1)/ operation that atomically switches the LVar into a
   -- frozen state.  Any threads waiting on the freeze are woken.
-  --
-  -- The frozen LVar provides a complete picture of the contents:
-  -- e.g. a whole set instead of one element, or the full/empty
+  -- 
+  -- The contents of a frozen LVar are fully observable:
+  -- e.g., a whole set instead of one element, or the full/empty
   -- information for an IVar, instead of just the payload.
   --
   -- However, note that `Frzn` LVars cannot be folded, because they may have
@@ -69,7 +69,7 @@
     -- version of the LVar contents with its original type:
     in AFoldable ls'
 
--- | Carries a Foldable type, but you don't get to know which one.
+-- | Carries a `Foldable` type, but you don't get to know which one.
 --   The purpose of this type is that `sortFreeze` should not have
 --   to impose a particular memory representation.
 data AFoldable a = forall f2 . F.Foldable f2 => AFoldable (f2 a)
@@ -81,13 +81,13 @@
 --------------------------------------------------------------------------------
 
 {-# INLINE unsafeCoerceLVar #-}
--- | A safer version of `unsafeCoerce#` for LVars only.
---   Note that it needs to change the contents type, because freezing is recursive.
+-- | A safer version of `unsafeCoerce#` (that is, with a slightly more constrained type) for LVars only.
+--   Note, that the type of the LVar's contents must be allowed to change, because freezing is recursive.
 unsafeCoerceLVar :: LVarData1 f => f s1 a -> f s2 b
 unsafeCoerceLVar = unsafeCoerce#
 
--- | Here we gain permission to expose the non-deterministic internal structure of an
--- LVar: namely, the order in which elements occur.  We pay the piper with an IO
+-- | Here we gain permission to expose the nondeterministic internal structure of an
+-- LVar: namely, the order in which its contents occur  We pay the piper with an `IO`
 -- action.
 unsafeTraversable :: LVarData1 f => f Frzn a -> IO (f Trvrsbl a)
 unsafeTraversable x = return (unsafeCoerceLVar x) 
diff --git a/Data/LVar/IStructure.hs b/Data/LVar/IStructure.hs
--- a/Data/LVar/IStructure.hs
+++ b/Data/LVar/IStructure.hs
@@ -11,8 +11,7 @@
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE InstanceSigs #-}
 
--- | An I-Structure, aka an Array of IVars.
---   This uses a boxed array.
+-- | An I-Structure, also known as an array of IVars, implemented using a boxed vector.
 
 module Data.LVar.IStructure
        (
@@ -48,8 +47,7 @@
 
 ------------------------------------------------------------------------------
 
--- | An I-Structure, aka an Array of IVars.
---   For now this really is a simple vector of IVars.
+-- | An I-Structure, also known as an array of IVars.
 newtype IStructure s a = IStructure (V.Vector (IV.IVar s a))
 
 -- unIStructure (IStructure lv) = lv
@@ -57,9 +55,9 @@
 instance Eq (IStructure s v) where
   IStructure vec1 == IStructure vec2 = vec1 == vec2
 
--- | An @IStructure@ can be treated as a generic container LVar.  However, the
+-- | An `IStructure` can be treated as a generic container LVar.  However, the
 -- polymorphic operations are less useful than the monomorphic ones exposed by this
--- module (e.g. @forEachHP@ vs. @addHandler@).
+-- module (e.g., @forEachHP@ vs. @addHandler@).
 instance LVarData1 IStructure where
   freeze orig@(IStructure vec) = WrapPar$ do
     -- No new alloc here, just time:
@@ -72,15 +70,16 @@
   -- Unlike the IStructure-specific forEach, this takes only values, not indices.
   addHandler mh is fn = forEachHP mh is (\ _k v -> fn v)
 
--- | The @IStructure@s in this module also have the special property that they
+-- | The `IStructure`s in this module also have the special property that they
 -- support a freeze operation which immediately yields a `Foldable` container
 -- without any sorting (see `snapFreeze`).
 instance OrderedLVarData1 IStructure where
   -- No extra work here...  
   snapFreeze is = unsafeCoerceLVar <$> G.freeze is
 
--- | As with all LVars, after freezing, map elements can be consumed. In the case of
--- this @IStructure@ implementation, it need only be `Frzn`, not `Trvrsbl`.
+-- As with all LVars, after freezing, map elements can be consumed. In
+-- the case of this @IStructure@ implementation, it need only be
+-- `Frzn`, not `Trvrsbl`.
 instance F.Foldable (IStructure Frzn) where
   foldr fn zer (IStructure vec) = 
     F.foldr (\ iv acc ->
@@ -89,13 +88,13 @@
                 Just x  -> fn x acc)
              zer vec
 
--- | Of course, the stronger `Trvrsbl` state is still fine for folding.
+-- Of course, the stronger `Trvrsbl` state is still fine for folding.
 instance F.Foldable (IStructure Trvrsbl) where
   foldr fn zer mp = F.foldr fn zer (castFrzn mp)
 
--- | @IStructure@ values can be returned as the result of a `runParThenFreeze`.
---   Hence they need a `DeepFrz` instace.
---   @DeepFrz@ is just a type-coercion.  No bits flipped at runtime.
+-- @IStructure@ values can be returned as the result of a
+-- `runParThenFreeze`.  Hence they need a `DeepFrz` instance.
+-- @DeepFrz@ is just a type-coercion.  No bits flipped at runtime.
 instance DeepFrz a => DeepFrz (IStructure s a) where
   type FrzType (IStructure s a) = IStructure Frzn (FrzType a)
   frz = unsafeCoerceLVar
@@ -114,22 +113,22 @@
 
 ------------------------------------------------------------------------------
 
--- | Retrieve the number of slots in the I-Structure.
+-- | Retrieve the number of slots in the `IStructure`.
 getLength :: IStructure s a -> Par d s Int
 getLength (IStructure vec) = return $! V.length vec
 
--- | Physical identity, just as with IORefs.
+-- Physical identity, just as with IORefs.
 -- instance Eq (IStructure s v) where
 --   IStructure lv1 == IStructure lv2 = state lv1 == state lv2 
 
 -- | Create a new, empty, monotonically growing 'IStructure' of a given size.
---   All entries start off as zero, which must be BOTTOM.
+--   All entries start off as zero, which must be \"bottom\".
 newIStructure :: Int -> Par d s (IStructure s elt)
 newIStructure len = fmap IStructure $
                     V.generateM len (\_ -> IV.new)
 
--- | This registers handlers on each internal IVar as it is created.
---   It should be more efficient than `newIStructure` followed by `forEachHP`
+-- | Register handlers on each internal IVar as it is created.
+--   This operation should be more efficient than `newIStructure` followed by `forEachHP`.
 newIStructureWithCallback :: Int -> (Int -> elt -> Par d s ()) -> Par d s (IStructure s elt)
 newIStructureWithCallback len fn =
   fmap IStructure $
@@ -138,9 +137,8 @@
       IV.whenFull Nothing iv (fn ix)
       return iv
 
--- | /O(N)/ complexity, unfortunately. This implementation of I-Structures requires
+-- | /O(N)/ complexity, unfortunately. This implementation of `IStructure`s requires
 -- freezing each of the individual IVars stored in the array.
--- 
 freezeIStructure :: IStructure s a -> LV.Par QuasiDet s (V.Vector (Maybe a))
 freezeIStructure (IStructure vec) = do
   v <- V.mapM IV.freezeIVar vec
@@ -148,10 +146,10 @@
 
 {-# INLINE forEachHP #-}
 -- | Add an (asynchronous) callback that listens for all new elements added to
--- the IStructure, optionally enrolled in a handler pool
+-- the `IStructure`, optionally enrolled in a handler pool.
 forEachHP :: -- (Eq a) =>
              Maybe HandlerPool           -- ^ pool to enroll in, if any
-          -> IStructure s a              -- ^ IStructure to listen to
+          -> IStructure s a              -- ^ `IStructure` to listen to
           -> (Int -> a -> Par d s ())    -- ^ callback
           -> Par d s ()
 forEachHP hp (IStructure vec) callb =
@@ -186,16 +184,16 @@
 
 {-# INLINE put #-}
 
--- | Put a single element in the array.  That slot must be previously empty.  (WHNF)
+-- | Put a single element in the `IStructure` at a given index.  That index must be previously empty.  (WHNF)
 -- Strict in the element being put in the set.
 put_ :: Eq elt => IStructure s elt -> Int -> elt -> Par d s ()
 put_ (IStructure vec) !ix !elm = IV.put_ (vec ! ix) elm
 
--- | Put a single element in the array.  This variant is deeply strict (`NFData`).
+-- | Put a single element in the `IStructure` at a given index.  This variant is deeply strict (`NFData`).
 put :: (NFData elt, Eq elt) => IStructure s elt -> Int -> elt -> Par d s ()
 put (IStructure vec) !ix !elm = IV.put (vec ! ix) elm
 
 {-# INLINE get #-}
--- | Wait for the indexed entry to contain a value and return that value.
+-- | Wait for the indexed entry to contain a value, and return that value.
 get :: Eq elt => IStructure s elt -> Int -> Par d s elt
 get (IStructure vec) !ix = IV.get (vec ! ix)
diff --git a/Data/LVar/IVar.hs b/Data/LVar/IVar.hs
--- a/Data/LVar/IVar.hs
+++ b/Data/LVar/IVar.hs
@@ -10,18 +10,25 @@
 
 {-|
 
-  `IVar`s are the very simplest form of `LVar`s.  They are either empty, or full, and
-  contain only at most a single value.
+  IVars are the very simplest form of LVars.  They are either empty or full, and
+  contain at most a single value.
 
-  For more explanation of using IVars in Haskell, see the @monad-par@ and
+  For further information on using IVars in Haskell, see the @monad-par@ and
   @meta-par@ packages and papers:
 
     * <http://hackage.haskell.org/package/monad-par>
 
     * <http://www.cs.indiana.edu/~rrnewton/papers/haskell2011_monad-par.pdf>
 
+    * <http://hackage.haskell.org/package/meta-par>
+
     * <http://www.cs.indiana.edu/~rrnewton/papers/2012-ICFP_meta-par.pdf>
 
+Unlike the @IVar@ type provided by @monad-par@, the 'IVar' type
+provided in this module permits repeated `put`s of the same value, in
+keeping with the lattice-based semantics of LVars in which a `put`
+takes the least upper bound of the old and new values.
+
  -}
 
 module Data.LVar.IVar
@@ -33,7 +40,7 @@
          -- * Derived IVar operations, same as in monad-par
         spawn, spawn_, spawnP,
 
-        -- * LVar style operations
+        -- * LVar-style operations
         freezeIVar, fromIVar, whenFull)
        where
 
@@ -60,16 +67,16 @@
 -- IVars implemented on top of (the idempotent implementation of) LVars
 ------------------------------------------------------------------------------
        
--- | An `IVar` is the simplest type of `LVar`.
+-- | An `IVar` is the simplest form of `LVar`.
 newtype IVar s a = IVar (LVar s (IORef (Maybe a)) a)
 -- the global data for an IVar a is a reference to Maybe a, while deltas are
 -- simply values of type a (taking the IVar from Nothing to Just):
 
--- | Physical equality just as with IORefs.
+-- | Physical equality, just as with `IORef`s.
 instance Eq (IVar s a) where
   (==) (IVar lv1) (IVar lv2) = state lv1 == state lv2
 
--- | An @IVar@ can be treated as a generic container LVar which happens to
+-- | An `IVar` can be treated as a generic container LVar which happens to
 -- contain at most one value!  Note, however, that the polymorphic operations are
 -- less useful than the monomorphic ones exposed by this module.
 instance LVarData1 IVar where  
@@ -79,13 +86,13 @@
     return (unsafeCoerceLVar orig)
   addHandler = whenFull
 
--- | DeepFrz is just a type-coercion.  No bits flipped at runtime:
+-- Just a type-coercion.  No bits flipped at runtime.
 instance DeepFrz a => DeepFrz (IVar s a) where
   type FrzType (IVar s a) = IVar Frzn (FrzType a)
   frz = unsafeCoerceLVar
 
--- | As with all other `Trvrsbl` LVars, the elements are traversable in a fixed
--- order.
+-- As with all other `Trvrsbl` LVars, the elements are traversable in
+-- a fixed order.
 instance F.Foldable (IVar Trvrsbl) where
   foldr fn zer (IVar lv) =
     case unsafeDupablePerformIO$ readIORef (state lv) of
@@ -109,17 +116,17 @@
       newLV $ newIORef Nothing
 
 {-# INLINE get #-}
--- | read the value in a @IVar@.  The 'get' can only return when the
+-- | Read the value in a IVar.  The 'get' can only return when the
 -- value has been written by a prior or concurrent @put@ to the same
--- @IVar@.
+-- IVar.
 get :: IVar s a -> Par d s a
 get (IVar (WrapLVar iv)) = WrapPar$ getLV iv globalThresh deltaThresh
   where globalThresh ref _ = readIORef ref    -- past threshold iff Jusbt _
         deltaThresh  x     = return $ Just x  -- always past threshold
 
 {-# INLINE put_ #-}
--- | put a value into a @IVar@.  Multiple 'put's to the same @IVar@
--- are not allowed, and result in a runtime error.  (Unless both values put happen to be @(==)@.)
+-- | Put a value into an IVar.  Multiple 'put's to the same IVar
+-- are not allowed, and result in a runtime error, unless the values put happen to be @(==)@.
 --         
 -- This function is always at least strict up to WHNF in the element put.
 put_ :: Eq a => IVar s a -> a -> Par d s ()
@@ -132,7 +139,7 @@
                                throw (LV.ConflictingPutExn$ "Multiple puts to an IVar! (obj "++show n2++" was "++show n1++")")
         update Nothing  = (Just x, Just x)
 
--- | The specialized freeze just for IVars.  It leaves the result in a natural format (`Maybe`).
+-- | A specialized freezing operation for IVars that leaves the result in a handy format (`Maybe`).
 freezeIVar :: IVar s a -> LV.Par QuasiDet s (Maybe a)
 freezeIVar (IVar (WrapLVar lv)) = WrapPar $ 
    do freezeLV lv
@@ -142,15 +149,15 @@
     globalThresh ref True = fmap Just $ readIORef ref
     deltaThresh _ = return Nothing
     
--- | Unpack a frozen `IVar` (as produced by a generic `freeze` operation) as a more
+-- | Unpack a frozen IVar (as produced by a generic `freeze` operation) as a more
 -- palatable data structure.
 fromIVar :: IVar Frzn a -> Maybe a
 fromIVar (IVar lv) = unsafeDupablePerformIO $ readIORef (state lv)
 
 {-# INLINE whenFull #-}
--- | Register a handler that fires when the `IVar` is filled, which, of course, only
+-- | Register a handler that fires when the IVar is filled, which, of course, only
 --   happens once.
-whenFull :: Maybe HandlerPool -> IVar s elt -> (elt -> Par d s ()) -> Par d s ()
+whenFull :: Maybe HandlerPool -> IVar s a -> (a -> Par d s ()) -> Par d s ()
 whenFull mh (IVar (WrapLVar lv)) fn = 
    WrapPar (LI.addHandler mh lv globalCB fn')
   where
@@ -170,12 +177,11 @@
 spawn p  = do r <- new;  fork (p >>= put r);   return r
 
 {-# INLINE spawn_ #-}
--- | A version of `spawn` that uses only weak-head-normal form rather than full `NFData`.
+-- | A version of `spawn` that uses only WHNF, rather than full `NFData`.
 spawn_ :: Eq a => Par d s a -> Par d s (IVar s a)
 spawn_ p = do r <- new;  fork (p >>= put_ r);  return r
 
 {-# INLINE spawnP #-}
--- | A variant that 
 spawnP :: (Eq a, NFData a) => a -> Par d s (IVar s a)
 spawnP a = spawn (return a)
 
diff --git a/Data/LVar/Internal/Pure.hs b/Data/LVar/Internal/Pure.hs
--- a/Data/LVar/Internal/Pure.hs
+++ b/Data/LVar/Internal/Pure.hs
@@ -6,17 +6,16 @@
 
 {-|
 
-This is NOT a datatype for the end-user.
+This is /not/ a datatype for the end-user.
 
 Rather, this module is for building /new/ LVar types in a comparatively easy way: by
-putting a pure value in a mutable container, and defining a LUB operation as a pure
+putting a pure value in a mutable container, and defining a @put@ operation as a pure
 function.
 
-The proof-obligation for the library-writer who uses this module is that they must
-guarantee that their LUB is a /true least-upper-bound/, obeying the appropriate laws
-for a join-semilattice:
-
- * <http://en.wikipedia.org/wiki/Semilattice>
+The data structure implementor who uses this module must guarantee
+that their @put@ operation computes a /least upper bound/, ensuring
+that the set of states that their LVar type can take on form a
+join-semilattice (<http://en.wikipedia.org/wiki/Semilattice>).
 
 -}
 
@@ -51,7 +50,7 @@
 newPureLVar st = WrapPar$ fmap (PureLVar . WrapLVar) $
                  LI.newLV $ newIORef st
 
--- | Wait until the Pure LVar has crossed a threshold and then unblock.  (In the
+-- | Wait until the pure LVar has crossed a threshold and then unblock.  (In the
 -- semantics, this is a singleton query set.)
 waitPureLVar :: (JoinSemiLattice t, Eq t) =>
                 PureLVar s t -> t -> Par d s ()
@@ -72,7 +71,7 @@
     putter _ = return (Just new)
 
 -- | Freeze the pure LVar, returning its exact value.
---   Subsequent puts will cause an error.
+--   Subsequent @put@s will raise an error.
 freezePureLVar :: PureLVar s t -> Par QuasiDet s t
 freezePureLVar (PureLVar (WrapLVar lv)) = WrapPar$ 
   do LI.freezeLV lv
@@ -84,40 +83,13 @@
 
 ------------------------------------------------------------
 
-
--- | Physical identity, just as with IORefs.
+-- | Physical identity, just as with `IORef`s.
 instance Eq (PureLVar s v) where
   PureLVar lv1 == PureLVar lv2 = state lv1 == state lv2 
 
--- | A `PureLVar` can be treated as a generic container LVar which happens to
--- contain exactly one value!
-  
--- instance LVarData1 PureLVar where
---   freeze orig@(PureLVar (WrapLVar lv)) = WrapPar$ do freezeLV lv; return (unsafeCoerceLVar orig)
---   sortFreeze is = AFoldable <$> freezeSet is
---   addHandler = forEachHP
-
--- -- | The `PureLVar`s in this module also have the special property that they support an
--- -- `O(1)` freeze operation which immediately yields a `Foldable` container
--- -- (`snapFreeze`).
--- instance OrderedLVarData1 PureLVar where
---   snapFreeze is = unsafeCoerceLVar <$> freeze is
-
--- -- | As with all LVars, after freezing, map elements can be consumed. In the case of
--- -- this `PureLVar` implementation, it need only be `Frzn`, not `Trvrsbl`.
--- instance F.Foldable (PureLVar Frzn) where
---   foldr fn zer (PureLVar lv) =
---     -- It's not changing at this point, no problem if duped:
---     let set = unsafeDupablePerformIO (readIORef (state lv)) in
---     F.foldr fn zer set 
-
--- -- | Of course, the stronger `Trvrsbl` state is still fine for folding.
--- instance F.Foldable (PureLVar Trvrsbl) where
---   foldr fn zer mp = F.foldr fn zer (castFrzn mp)
-
--- | `PureLVar` values can be returned as the result of a `runParThenFreeze`.
---   Hence they need a `DeepFrz` instace.
---   @DeepFrz@ is just a type-coercion.  No bits flipped at runtime.
+-- `PureLVar` values can be returned as the result of a
+--  `runParThenFreeze`.  Hence they need a `DeepFrz` instance.
+--  @DeepFrz@ is just a type-coercion.  No bits flipped at runtime.
 instance DeepFrz a => DeepFrz (PureLVar s a) where
   -- We can't be sure that someone won't put an LVar value inside a
   -- PureLVar!  Therefore we have to apply FrzType recursively.
diff --git a/Data/LVar/PureMap.hs b/Data/LVar/PureMap.hs
--- a/Data/LVar/PureMap.hs
+++ b/Data/LVar/PureMap.hs
@@ -11,11 +11,11 @@
 
 {-|
 
-  This module provides finite maps that only grow.  It is based on the popular `Data.Map`
+  This module provides finite maps that only grow.  It is based on the popular "Data.Map"
   balanced-tree representation of maps.  Thus scalability is /not/ good for this
   implementation.  However, there are some interoperability benefits.  For example,
   after running a parallel computation with a map result, this module can produce a
-  `Data.Map` in /O(1)/ without copying, which may be useful downstream.
+  `Map` in /O(1)/ without copying, which may be useful downstream.
 
  -}
 
@@ -26,18 +26,18 @@
          newEmptyMap, newMap, newFromList,
          insert, 
          getKey, waitValue, waitSize, modify, 
-
-         -- * Freezing results (Quasi-determinism) 
-         freezeMap, fromIMap,
          
          -- * Iteration and callbacks
          forEach, forEachHP,
          withCallbacksThenFreeze,
 
+         -- * Quasi-deterministic operations
+         freezeMap, fromIMap,
+
          -- * Higher-level derived operations
          copy, traverseMap, traverseMap_,  union,
          
-         -- * Alternate versions of derived ops that expose HandlerPools they create.
+         -- * Alternate versions of derived ops that expose @HandlerPool@s they create
          traverseMapHP, traverseMapHP_, unionHP
        ) where
 
@@ -61,8 +61,6 @@
 import           System.IO.Unsafe (unsafePerformIO, unsafeDupablePerformIO)
 import           System.Mem.StableName (makeStableName, hashStableName)
 
-type QPar = Par QuasiDet  -- Shorthand.
-
 ------------------------------------------------------------------------------
 -- IMaps implemented on top of LVars:
 ------------------------------------------------------------------------------
@@ -71,7 +69,7 @@
 --  `STRef`) in addition to the @a@ parameter that describes the type of elements
 -- in the set.
 -- 
--- Performance note: There is only ONE mutable location in this implementation.  Thus
+-- Performance note: There is only /one/ mutable location in this implementation.  Thus
 -- it is not a scalable implementation.
 newtype IMap k s v = IMap (LVar s (IORef (M.Map k v)) (k,v))
 
@@ -88,25 +86,26 @@
   sortFrzn (IMap lv) = AFoldable$ unsafeDupablePerformIO (readIORef (state lv))
 
 -- | The `IMap`s in this module also have the special property that they support an
--- `O(1)` freeze operation which immediately yields a `Foldable` container
+-- /O(1)/ freeze operation which immediately yields a `Foldable` container
 -- (`snapFreeze`).
 instance OrderedLVarData1 (IMap k) where
   snapFreeze is = unsafeCoerceLVar <$> freeze is
 
--- | As with all LVars, after freezing, map elements can be consumed. In the case of
--- this `IMap` implementation, it need only be `Frzn`, not `Trvrsbl`.
+-- As with all LVars, after freezing, map elements can be consumed. In
+-- the case of this `IMap` implementation, it need only be `Frzn`, not
+-- `Trvrsbl`.
 instance F.Foldable (IMap k Frzn) where
   foldr fn zer (IMap lv) =
     let set = unsafeDupablePerformIO (readIORef (state lv)) in
     F.foldr fn zer set 
 
--- | Of course, the stronger `Trvrsbl` state is still fine for folding.
+-- Of course, the stronger `Trvrsbl` state is still fine for folding.
 instance F.Foldable (IMap k Trvrsbl) where
   foldr fn zer mp = F.foldr fn zer (castFrzn mp)
 
--- | `IMap` values can be returned as the result of a `runParThenFreeze`.
---   Hence they need a `DeepFrz` instace.
---   @DeepFrz@ is just a type-coercion.  No bits flipped at runtime.
+-- `IMap` values can be returned as the result of a
+--  `runParThenFreeze`.  Hence they need a `DeepFrz` instance.
+--  @DeepFrz@ is just a type-coercion.  No bits flipped at runtime.
 instance DeepFrz a => DeepFrz (IMap k s a) where
   type FrzType (IMap k s a) = IMap k Frzn (FrzType a)
   frz = unsafeCoerceLVar
@@ -140,7 +139,7 @@
 
 -- | Register a per-element callback, then run an action in this context, and freeze
 -- when all (recursive) invocations of the callback are complete.  Returns the final
--- valueof the Map variable.
+-- value of the provided action.
 withCallbacksThenFreeze :: forall k v b s . Eq b =>
                            IMap k s v -> (k -> v -> QPar s ()) -> QPar s b -> QPar s b
 withCallbacksThenFreeze (IMap (WrapLVar lv)) callback action =
@@ -164,7 +163,7 @@
         IV.put_ resIV res
 
 -- | Add an (asynchronous) callback that listens for all new key/value pairs added to
--- the map, optionally enrolled in a handler pool
+-- the map, optionally enrolled in a handler pool.
 forEachHP :: Maybe HandlerPool           -- ^ optional pool to enroll in 
           -> IMap k s v                  -- ^ Map to listen to
           -> (k -> v -> Par d s ())      -- ^ callback
@@ -180,13 +179,13 @@
         traverseWithKey_ (\ k v -> forkHP mh$ callb k v) mp
         
 -- | Add an (asynchronous) callback that listens for all new new key/value pairs added to
--- the map
+-- the map.
 forEach :: IMap k s v -> (k -> v -> Par d s ()) -> Par d s ()
 forEach = forEachHP Nothing 
 
 -- | Put a single entry into the map.  Strict (WHNF) in the key and value.
 -- 
---   As with other container LVars, if an key is put multiple times, the values had
+--   As with other container LVars, if a key is inserted multiple times, the values had
 --   better be equal @(==)@, or a multiple-put error is raised.
 insert :: (Ord k, Eq v) =>
           k -> v -> IMap k s v -> Par d s () 
@@ -203,18 +202,18 @@
           then (mp',Just (key,elm))
           else (mp, Nothing)
 
--- | IMap's containing other LVars have some additional capabilities compared to
+-- | `IMap`s containing other LVars have some additional capabilities compared to
 -- those containing regular Haskell data.  In particular, it is possible to modify
 -- existing entries (monotonically).  Further, this `modify` function implicitly
--- inserts a "bottom" element if there is no existing entry for the key.
---
+-- inserts a \"bottom\" element if there is no existing entry for the key.
+-- 
 -- Unfortunately, that means that this takes another computation for creating new
--- "bottom" elements for the nested LVars stored inside the Map.
+-- \"bottom\" elements for the nested LVars stored inside the `IMap`.
 modify :: forall f a b d s key . (Ord key, LVarData1 f, Show key, Ord a) =>
           IMap key s (f s a)
           -> key                  -- ^ The key to lookup.
-          -> (Par d s (f s a))    -- ^ Create a new "bottom" element whenever an entry is not present.
-          -> (f s a -> Par d s b) -- ^ The computation to apply on the right-hand-side of the keyed entry.
+          -> (Par d s (f s a))    -- ^ Create a new \"bottom\" element whenever an entry is not present.
+          -> (f s a -> Par d s b) -- ^ The computation to apply on the right-hand side of the keyed entry.
           -> Par d s b
 modify (IMap lv) key newBottom fn = WrapPar $ do 
   let ref = state lv      
@@ -263,7 +262,7 @@
                       | otherwise = return Nothing 
 
 
--- | Wait on the SIZE of the map, not its contents.
+-- | Wait on the /size/ of the map, not its contents.
 waitSize :: Int -> IMap k s v -> Par d s ()
 waitSize !sz (IMap (WrapLVar lv)) = WrapPar $
     getLV lv globalThresh deltaThresh
@@ -277,15 +276,17 @@
     -- the threshold.a
     deltaThresh _ = globalThresh (L.state lv) False
 
--- | Get the exact contents of the map  Using this may cause your
+-- | Get the exact contents of the map.  As with any
+-- quasi-deterministic operation, using `freezeSet` may cause your
 -- program to exhibit a limited form of nondeterminism: it will never
 -- return the wrong answer, but it may include synchronization bugs
 -- that can (nondeterministically) cause exceptions.
 --
--- This Data.Map based LVar has the property that you can
--- retrieve the full set without any IO, and without nondeterminism
--- leaking.  (This is because the internal order is fixed for the
--- tree-based Data.Set.)    
+-- This "Data.Map"-based implementation has the special property that
+-- you can retrieve the full set without any `IO`, and without
+-- nondeterminism leaking.  (This is because the internal order is
+-- fixed for the tree-based representation of maps that "Data.Map"
+-- uses.)
 freezeMap :: IMap k s v -> QPar s (M.Map k v)
 freezeMap (IMap (WrapLVar lv)) = WrapPar $
    do freezeLV lv
@@ -305,13 +306,14 @@
 -- Higher level routines that could (mostly) be defined using the above interface.
 --------------------------------------------------------------------------------
 
--- | Establish monotonic map between the input and output sets.  Produce a new result
--- based on each element, while leaving the keys the same.
+-- | Establish a monotonic map between the input and output sets.
+-- Produce a new result based on each element, while leaving the keys
+-- the same.
 traverseMap :: (Ord k, Eq b) =>
                (k -> a -> Par d s b) -> IMap k s a -> Par d s (IMap k s b)
 traverseMap f s = traverseMapHP Nothing f s
 
--- | An imperative-style, inplace version of 'traverseMap' that takes the output set
+-- | An imperative-style, in-place version of 'traverseMap' that takes the output set
 -- as an argument.
 traverseMap_ :: (Ord k, Eq b) =>
                 (k -> a -> Par d s b) -> IMap k s a -> IMap k s b -> Par d s ()
@@ -319,7 +321,6 @@
 
 -- | Return a new map which will (ultimately) contain everything in either input
 -- map.  Conflicting entries will result in a multiple put exception.
--- Optionally ties the handlers to a pool.
 union :: (Ord k, Eq a) => IMap k s a -> IMap k s a -> Par d s (IMap k s a)
 union = unionHP Nothing
 
@@ -334,7 +335,7 @@
 copy :: (Ord k, Eq v) => IMap k s v -> Par d s (IMap k s v)
 copy = traverseMap (\ _ x -> return x)
 
--- | Variant that optionally ties the handlers to a pool.
+-- | A variant of `traverseMap` that optionally ties the handlers to a pool.
 traverseMapHP :: (Ord k, Eq b) =>
                  Maybe HandlerPool -> (k -> a -> Par d s b) -> IMap k s a ->
                  Par d s (IMap k s b)
@@ -343,7 +344,7 @@
   traverseMapHP_ mh fn set os  
   return os
 
--- | Variant that optionally ties the handlers to a pool.
+-- | A variant of `traverseMap_` that optionally ties the handlers to a pool.
 traverseMapHP_ :: (Ord k, Eq b) =>
                   Maybe HandlerPool -> (k -> a -> Par d s b) -> IMap k s a -> IMap k s b ->
                   Par d s ()
@@ -352,8 +353,9 @@
     x' <- fn k x
     insert k x' os
 
--- | Variant that optionally ties the handlers in the resulting set to the same
--- handler pool as those in the two input sets.
+-- | A variant of `union` that optionally ties the handlers in the
+-- resulting set to the same handler pool as those in the two input
+-- sets.
 unionHP :: (Ord k, Eq a) => Maybe HandlerPool ->
            IMap k s a -> IMap k s a -> Par d s (IMap k s a)
 unionHP mh m1 m2 = do
@@ -367,4 +369,3 @@
 unsafeName x = unsafePerformIO $ do 
    sn <- makeStableName x
    return (hashStableName sn)
-
diff --git a/Data/LVar/PureSet.hs b/Data/LVar/PureSet.hs
--- a/Data/LVar/PureSet.hs
+++ b/Data/LVar/PureSet.hs
@@ -13,11 +13,11 @@
 
 {-|
 
-  This module provides sets that only grow.  It is based on the popular `Data.Set`
-  balanced-tree representation of sets.  Thus scalability is not good for this
+  This module provides sets that only grow.  It is based on the popular "Data.Set"
+  balanced-tree representation of sets.  Thus scalability is /not/ good for this
   implementation.  However, there are some interoperability benefits.  For exmaple,
   after running a parallel computation with a set result, this module can produce a
-  `Data.Set` in /O(1)/ without copying, which may be useful downstream.
+  `Set` in /O(1)/ without copying, which may be useful downstream.
 
  -}
 
@@ -39,7 +39,7 @@
          copy, traverseSet, traverseSet_, union, intersection,
          cartesianProd, cartesianProds, 
 
-         -- * Alternate versions of derived ops that expose HandlerPools they create.
+         -- * Alternate versions of derived ops that expose @HandlerPool@s they create
          traverseSetHP, traverseSetHP_, unionHP, intersectionHP,
          cartesianProdHP, cartesianProdsHP
        ) where
@@ -69,11 +69,11 @@
 -- an `STRef`) in addition to the @a@ parameter that describes the type of elements
 -- in the set.
 --
--- Performance note: There is only ONE mutable location in this implementation.  Thus
+-- Performance note: There is only /one/ mutable location in this implementation.  Thus
 -- it is not a scalable implementation.
 newtype ISet s a = ISet (LVar s (IORef (S.Set a)) a)
 
--- | Physical identity, just as with IORefs.
+-- | Physical identity, just as with `IORef`s.
 instance Eq (ISet s v) where
   ISet lv1 == ISet lv2 = state lv1 == state lv2 
 
@@ -86,27 +86,27 @@
   sortFrzn (ISet lv) = AFoldable$ unsafeDupablePerformIO (readIORef (state lv))
 
 -- | The `ISet`s in this module also have the special property that they support an
--- `O(1)` freeze operation which immediately yields a `Foldable` container
+-- /O(1)/ freeze operation which immediately yields a `Foldable` container
 -- (`snapFreeze`).
 instance OrderedLVarData1 ISet where
   snapFreeze is = unsafeCoerceLVar <$> freeze is
 
--- | As with all LVars, after freezing, map elements can be consumed. In the case of
--- this `ISet` implementation, it need only be `Frzn`, not `Trvrsbl`.
+-- As with all LVars, after freezing, map elements can be consumed. In
+-- the case of this `ISet` implementation, it need only be `Frzn`, not
+-- `Trvrsbl`.
 instance F.Foldable (ISet Frzn) where
   foldr fn zer (ISet lv) =
     -- It's not changing at this point, no problem if duped:
     let set = unsafeDupablePerformIO (readIORef (state lv)) in
     F.foldr fn zer set 
 
--- | Of course, the stronger `Trvrsbl` state is still fine for folding.
+-- Of course, the stronger `Trvrsbl` state is still fine for folding.
 instance F.Foldable (ISet Trvrsbl) where
   foldr fn zer mp = F.foldr fn zer (castFrzn mp)
 
-
--- | `ISet` values can be returned as the result of a `runParThenFreeze`.
---   Hence they need a `DeepFrz` instace.
---   @DeepFrz@ is just a type-coercion.  No bits flipped at runtime.
+-- `ISet` values can be returned as the result of a
+--  `runParThenFreeze`.  Hence they need a `DeepFrz` instance.
+--  @DeepFrz@ is just a type-coercion.  No bits flipped at runtime.
 instance DeepFrz a => DeepFrz (ISet s a) where
   type FrzType (ISet s a) = ISet Frzn (FrzType a)
   frz = unsafeCoerceLVar
@@ -121,7 +121,7 @@
 instance Show a => Show (ISet Trvrsbl a) where
   show = show . castFrzn
 
--- | Create a new, empty, monotonically growing 'ISet'.
+-- | Create a new, empty, monotonically growing set.
 newEmptySet :: Par d s (ISet s a)
 newEmptySet = newSet S.empty
 
@@ -129,7 +129,7 @@
 newSet :: S.Set a -> Par d s (ISet s a)
 newSet s = WrapPar$ fmap (ISet . WrapLVar) $ newLV$ newIORef s
 
--- | Create a new 'ISet' drawing initial elements from an existing list.
+-- | Create a new set drawing initial elements from an existing list.
 newFromList :: Ord a => [a] -> Par d s (ISet s a)
 newFromList ls = newSet (S.fromList ls)
 
@@ -139,13 +139,10 @@
 -- Quasi-deterministic ops:
 --------------------------------------------------------------------------------
 
--- Just a shorthand for below:
-type QPar = Par QuasiDet 
-
 -- | Freeze an 'ISet' after a specified callback/handler is done running.  This
--- differs from withCallbacksThenFreeze by not taking an additional action to run in
+-- differs from `withCallbacksThenFreeze` by not taking an additional action to run in
 -- the context of the handlers.
---
+-- 
 --    (@'freezeSetAfter' 's' 'f' == 'withCallbacksThenFreeze' 's' 'f' 'return ()' @)
 freezeSetAfter :: ISet s a -> (a -> QPar s ()) -> QPar s ()
 freezeSetAfter s f = withCallbacksThenFreeze s f (return ())
@@ -175,15 +172,17 @@
         res <- action -- Any additional puts here trigger the callback.
         IV.put_ resIV res
 
--- | Get the exact contents of the set.  Using this may cause your
+-- | Get the exact contents of the set.  As with any
+-- quasi-deterministic operation, using `freezeSet` may cause your
 -- program to exhibit a limited form of nondeterminism: it will never
 -- return the wrong answer, but it may include synchronization bugs
 -- that can (nondeterministically) cause exceptions.
 --
--- This Data.Set based LVar has the special property that you can
--- retrieve the full set without any IO, and without nondeterminism
--- leaking.  (This is because the internal order is fixed for the
--- tree-based Data.Set.)
+-- This "Data.Set"-based implementation has the special property that
+-- you can retrieve the full set without any `IO`, and without
+-- nondeterminism leaking.  (This is because the internal order is
+-- fixed for the tree-based representation of sets that "Data.Set"
+-- uses.)
 freezeSet :: ISet s a -> QPar s (S.Set a)
 freezeSet (ISet (WrapLVar lv)) = WrapPar $ 
    do freezeLV lv
@@ -204,7 +203,7 @@
 --------------------------------------------------------------------------------
 
 -- | Add an (asynchronous) callback that listens for all new elements added to
--- the set, optionally enrolled in a handler pool
+-- the set, optionally enrolled in a handler pool.
 forEachHP :: Maybe HandlerPool           -- ^ pool to enroll in, if any
           -> ISet s a                    -- ^ Set to listen to
           -> (a -> Par d s ())           -- ^ callback
@@ -219,7 +218,7 @@
         F.foldlM (\() v -> forkHP hp $ callb v) () set -- Non-allocating traversal.
 
 -- | Add an (asynchronous) callback that listens for all new elements added to
--- the set
+-- the set.
 forEach :: ISet s a -> (a -> Par d s ()) -> Par d s ()
 forEach = forEachHP Nothing
 
@@ -251,7 +250,7 @@
                    | otherwise  = return Nothing 
 
 
--- | Wait on the SIZE of the set, not its contents.
+-- | Wait on the /size/ of the set, not its contents.
 waitSize :: Int -> ISet s a -> Par d s ()
 waitSize !sz (ISet lv) = WrapPar$
     getLV (unWrapLVar lv) globalThresh deltaThresh
@@ -274,11 +273,11 @@
 copy :: Ord a => ISet s a -> Par d s (ISet s a)
 copy = traverseSet return
 
--- | Establish monotonic map between the input and output sets.
+-- | Establish a monotonic map between the input and output sets.
 traverseSet :: Ord b => (a -> Par d s b) -> ISet s a -> Par d s (ISet s b)
 traverseSet f s = traverseSetHP Nothing f s
 
--- | An imperative-style, inplace version of 'traverseSet' that takes the output set
+-- | An imperative-style, in-place version of 'traverseSet' that takes the output set
 -- as an argument.
 traverseSet_ :: Ord b => (a -> Par d s b) -> ISet s a -> ISet s b -> Par d s ()
 traverseSet_ f s o = void $ traverseSetHP_ Nothing f s o
@@ -291,11 +290,11 @@
 intersection :: Ord a => ISet s a -> ISet s a -> Par d s (ISet s a)
 intersection = intersectionHP Nothing
 
--- | Cartesian product of two sets.
+-- | Take the cartesian product of two sets.
 cartesianProd :: (Ord a, Ord b) => ISet s a -> ISet s b -> Par d s (ISet s (a,b))
 cartesianProd s1 s2 = cartesianProdHP Nothing s1 s2 
   
--- | Takes the cartesian product of several sets.
+-- | Take the cartesian product of several sets.
 cartesianProds :: Ord a => [ISet s a] -> Par d s (ISet s [a])
 cartesianProds ls = cartesianProdsHP Nothing ls
 
@@ -303,7 +302,7 @@
 -- Alternate versions of functions that EXPOSE the HandlerPools
 --------------------------------------------------------------------------------
 
--- | Variant that optionally ties the handlers to a pool.
+-- | Variant of `traverseSet` that optionally ties the handlers to a pool.
 traverseSetHP :: Ord b => Maybe HandlerPool -> (a -> Par d s b) -> ISet s a ->
                  Par d s (ISet s b)
 traverseSetHP mh fn set = do
@@ -311,7 +310,7 @@
   traverseSetHP_ mh fn set os  
   return os
 
--- | Variant that optionally ties the handlers to a pool.
+-- | Variant of `traverseSet_` that optionally ties the handlers to a pool.
 traverseSetHP_ :: Ord b => Maybe HandlerPool -> (a -> Par d s b) -> ISet s a -> ISet s b ->
                   Par d s ()
 traverseSetHP_ mh fn set os = do
@@ -319,7 +318,7 @@
     x' <- fn x
     insert x' os
 
--- | Variant that optionally ties the handlers in the resulting set to the same
+-- | Variant of `union` that optionally ties the handlers in the resulting set to the same
 -- handler pool as those in the two input sets.
 unionHP :: Ord a => Maybe HandlerPool -> ISet s a -> ISet s a -> Par d s (ISet s a)
 unionHP mh s1 s2 = do
@@ -328,7 +327,7 @@
   forEachHP mh s2 (`insert` os)
   return os
 
--- | Variant that optionally ties the handlers in the resulting set to the same
+-- | Variant of `intersection` that optionally ties the handlers in the resulting set to the same
 -- handler pool as those in the two input sets.
 intersectionHP :: Ord a => Maybe HandlerPool -> ISet s a -> ISet s a -> Par d s (ISet s a)
 -- Can we do intersection with only the public interface?  It should be monotonic.
diff --git a/Data/LVar/SLMap.hs b/Data/LVar/SLMap.hs
--- a/Data/LVar/SLMap.hs
+++ b/Data/LVar/SLMap.hs
@@ -14,12 +14,13 @@
 
 {-|
 
-  This module provides finite maps that only grow.  It is based on a concurrent-skip-list
-  implementation of maps.
+This module provides finite maps that only grow. It is based on a
+/concurrent skip list/ implementation of maps.
 
-  Note that this module provides almost the same interface as "Data.LVar.PureMap",
-  but this module is usually more efficient.  However, it's always good to test muliple
-  data structures if you have a performance-critical use case.
+This module is usually a more efficient alternative to
+`Data.LVar.PureMap`, and provides almost the same interface. However,
+it's always good to test multiple data structures if you have a
+performance-critical use case.
 
  -}
 
@@ -30,7 +31,10 @@
          IMap,
          newEmptyMap, newMap, newFromList,
          insert, 
-         getKey, waitSize, modify, freezeMap,
+         getKey, waitSize, modify,
+
+         -- * Quasi-deterministic operations
+         freezeMap,
          -- waitValue, 
 
          -- * Iteration and callbacks
@@ -40,7 +44,7 @@
          -- * Higher-level derived operations
          copy, traverseMap, traverseMap_, 
          
-         -- * Alternate versions of derived ops that expose HandlerPools they create.
+         -- * Alternate versions of derived ops that expose @HandlerPool@s they create
          traverseMapHP, traverseMapHP_, unionHP,
 
        ) where
@@ -68,8 +72,6 @@
 import           GHC.Prim          (unsafeCoerce#)
 import           Prelude
 
-type QPar = Par QuasiDet -- Shorthand used below.
-
 ------------------------------------------------------------------------------
 -- IMaps implemented vis SkipListMap
 ------------------------------------------------------------------------------
@@ -111,14 +113,14 @@
           SLM.foldlWithKey (\() _k v -> forkHP mh $ callb v) () slm
 
 -- | The `IMap`s in this module also have the special property that they support an
--- `O(1)` freeze operation which immediately yields a `Foldable` container
+-- /O(1)/ freeze operation which immediately yields a `Foldable` container
 -- (`snapFreeze`).
 instance OrderedLVarData1 (IMap k) where
   snapFreeze is = unsafeCoerceLVar <$> freeze is
 
--- | `IMap` values can be returned as the result of a `runParThenFreeze`.
---   Hence they need a `DeepFrz` instace.
---   @DeepFrz@ is just a type-coercion.  No bits flipped at runtime.
+-- `IMap` values can be returned as the result of a
+-- `runParThenFreeze`.  Hence they need a `DeepFrz` instance.
+-- @DeepFrz@ is just a type-coercion.  No bits flipped at runtime.
 instance DeepFrz a => DeepFrz (IMap k s a) where
   type FrzType (IMap k s a) = IMap k Frzn (FrzType a)
   frz = unsafeCoerceLVar
@@ -148,13 +150,13 @@
                    ) mp
   return slm
 
--- | Create a new 'IMap' drawing initial elements from an existing list.
+-- | Create a new map drawing initial elements from an existing list.
 newFromList :: (Ord k, Eq v) =>
                [(k,v)] -> Par d s (IMap k s v)
 newFromList ls = newFromList_ ls defaultLevels
 
--- | Create a new 'IMap' drawing initial elements from an existing list, with
--- the given number of skiplist levels.
+-- | Create a new map drawing initial elements from an existing list, with
+-- the given number of skip list levels.
 newFromList_ :: Ord k => [(k,v)] -> Int -> Par d s (IMap k s v)
 newFromList_ ls n = do  
   m@(IMap lv) <- newEmptyMap_ n
@@ -198,7 +200,7 @@
         SLM.foldlWithKey (\() k v -> forkHP mh $ callb k v) () slm
         
 -- | Add an (asynchronous) callback that listens for all new new key/value pairs added to
--- the map
+-- the map.
 forEach :: IMap k s v -> (k -> v -> Par d s ()) -> Par d s ()
 forEach = forEachHP Nothing         
 
@@ -212,16 +214,16 @@
             Added _ -> return $ Just (key, elm)
             Found _ -> throw$ ConflictingPutExn$ "Multiple puts to one entry in an IMap!"
           
--- | IMap's containing other LVars have some additional capabilities compared to
+-- | `IMap`s containing other LVars have some additional capabilities compared to
 -- those containing regular Haskell data.  In particular, it is possible to modify
 -- existing entries (monotonically).  Further, this `modify` function implicitly
--- inserts a "bottom" element if there is no existing entry for the key.
+-- inserts a \"bottom\" element if there is no existing entry for the key.
 --
 modify :: forall f a b d s key . (Ord key, LVarData1 f, Show key, Ord a) =>
           IMap key s (f s a)
           -> key                  -- ^ The key to lookup.
-          -> (Par d s (f s a))    -- ^ Create a new "bottom" element whenever an entry is not present.
-          -> (f s a -> Par d s b) -- ^ The computation to apply on the right-hand-side of the keyed entry.
+          -> (Par d s (f s a))    -- ^ Create a new \"bottom\" element whenever an entry is not present.
+          -> (f s a -> Par d s b) -- ^ The computation to apply on the right-hand side of the keyed entry.
           -> Par d s b
 modify (IMap (WrapLVar lv)) key newBottom fn = do
     act <- WrapPar $ putLV_ lv putter
@@ -258,12 +260,13 @@
     -- the threshold.a
     deltaThresh _ = globalThresh (L.state lv) False
 
--- | Get the exact contents of the map  Using this may cause your
+-- | Get the exact contents of the map.  As with any
+-- quasi-deterministic operation, using `freezeMap` may cause your
 -- program to exhibit a limited form of nondeterminism: it will never
 -- return the wrong answer, but it may include synchronization bugs
 -- that can (nondeterministically) cause exceptions.
 --
--- This is an O(1) operation that doesn't copy the in-memory representation of the
+-- This is an /O(1)/ operation that doesn't copy the in-memory representation of the
 -- IMap.
 freezeMap :: Ord k => IMap k s v -> QPar s (IMap k Frzn v)
 -- freezeMap (IMap (WrapLVar lv)) = return (IMap (WrapLVar lv))
@@ -279,13 +282,13 @@
 -- Higher level routines that could (mostly) be defined using the above interface.
 --------------------------------------------------------------------------------
 
--- | Establish monotonic map between the input and output sets.  Produce a new result
+-- | Establish a monotonic map between the input and output map  Produce a new result
 -- based on each element, while leaving the keys the same.
 traverseMap :: (Ord k, Eq b) =>
                (k -> a -> Par d s b) -> IMap k s a -> Par d s (IMap k s b)
 traverseMap f s = traverseMapHP Nothing f s
 
--- | An imperative-style, inplace version of 'traverseMap' that takes the output set
+-- | An imperative-style, in-place version of 'traverseMap' that takes the output map
 -- as an argument.
 traverseMap_ :: (Ord k, Eq b) =>
                 (k -> a -> Par d s b) -> IMap k s a -> IMap k s b -> Par d s ()
@@ -300,7 +303,7 @@
 copy :: (Ord k, Eq v) => IMap k s v -> Par d s (IMap k s v)
 copy = traverseMap (\ _ x -> return x)
 
--- | Variant that optionally ties the handlers to a pool.
+-- | Variant of `traverseMap` that optionally ties the handlers to a pool.
 traverseMapHP :: (Ord k, Eq b) =>
                  Maybe HandlerPool -> (k -> a -> Par d s b) -> IMap k s a ->
                  Par d s (IMap k s b)
@@ -309,7 +312,7 @@
   traverseMapHP_ mh fn set os  
   return os
 
--- | Variant that optionally ties the handlers to a pool.
+-- | Variant of `traverseMap_` that optionally ties the handlers to a pool.
 traverseMapHP_ :: (Ord k, Eq b) =>
                   Maybe HandlerPool -> (k -> a -> Par d s b) -> IMap k s a -> IMap k s b ->
                   Par d s ()
@@ -333,8 +336,9 @@
 -- Operations on frozen Maps
 --------------------------------------------------------------------------------
 
--- | As with all LVars, after freezing, map elements can be consumed. In the case of
--- this `IMap` implementation, it need only be `Frzn`, not `Trvrsbl`.
+-- As with all LVars, after freezing, map elements can be consumed. In
+-- the case of this `IMap` implementation, it need only be `Frzn`, not
+-- `Trvrsbl`.
 instance F.Foldable (IMap k Frzn) where
   -- Note: making these strict for now:  
   foldr fn zer (IMap (WrapLVar lv)) =
@@ -342,7 +346,7 @@
     SLM.foldlWithKey (\ a _k v -> return (fn v a))
                      zer (L.state lv)
 
--- | Of course, the stronger `Trvrsbl` state is still fine for folding.
+-- Of course, the stronger `Trvrsbl` state is still fine for folding.
 instance F.Foldable (IMap k Trvrsbl) where
   foldr fn zer mp = F.foldr fn zer (castFrzn mp)
 
diff --git a/Data/LVar/SLSet.hs b/Data/LVar/SLSet.hs
--- a/Data/LVar/SLSet.hs
+++ b/Data/LVar/SLSet.hs
@@ -13,12 +13,13 @@
 
 {-|
 
-  This module provides sets that only grow.  It is based on a concurrent-skip-list
-  implementation of sets.
+This module provides sets that only grow.  It is based on a
+/concurrent skip list/ representation of sets.
 
-  Note that this module provides almost the same interface as "Data.LVar.PureSet",
-  but this module is usually more efficient.  However, it's always good to test muliple
-  data structures if you have a performance-critical use case.
+This module is usually a more efficient alternative to
+"Data.LVar.PureSet", and provides almost the same interface.  However,
+it's always good to test multiple data structures if you have a
+performance-critical use case.
 
  -}
 
@@ -40,7 +41,7 @@
          copy, traverseSet, traverseSet_, union, intersection,
          cartesianProd, cartesianProds, 
 
-         -- * Alternate versions of derived ops that expose HandlerPools they create.
+         -- * Alternate versions of derived ops that expose @HandlerPool@s they create
          traverseSetHP, traverseSetHP_,
          cartesianProdHP, cartesianProdsHP
        ) where 
@@ -77,7 +78,7 @@
 data ISet s a = Ord a => ISet {-# UNPACK #-}!(LVar s (SLM.SLMap a ()) a)
 -- TODO: Address the possible inefficiency of carrying Ord dictionaries at runtime.
 
--- | Physical identity, just as with IORefs.
+-- | Physical identity, just as with `IORef`s.
 instance Eq (ISet s v) where
   ISet slm1 == ISet slm2 = state slm1 == state slm2
   
@@ -93,14 +94,14 @@
 
 
 -- | The `ISet`s in this module also have the special property that they support an
--- `O(1)` freeze operation which immediately yields a `Foldable` container
+-- /O(1)/ freeze operation which immediately yields a `Foldable` container
 -- (`snapFreeze`).
 instance OrderedLVarData1 ISet where
   snapFreeze is = unsafeCoerceLVar <$> freeze is
 
--- | `ISet` values can be returned as the result of a `runParThenFreeze`.
---   Hence they need a `DeepFrz` instance.
---   @DeepFrz@ is just a type-coercion.  No bits flipped at runtime.
+-- `ISet` values can be returned as the result of a
+--  `runParThenFreeze`.  Hence they need a `DeepFrz` instance.
+--  @DeepFrz@ is just a type-coercion.  No bits flipped at runtime.
 instance DeepFrz a => DeepFrz (ISet s a) where
   type FrzType (ISet s a) = ISet Frzn (FrzType a)
   frz = unsafeCoerceLVar
@@ -124,15 +125,16 @@
     Just () -> True
     Nothing -> False
 
--- | As with all LVars, after freezing, map elements can be consumed. In the case of
--- this `ISet` implementation, it need only be `Frzn`, not `Trvrsbl`.
+-- As with all LVars, after freezing, map elements can be consumed. In
+-- the case of this `ISet` implementation, it need only be `Frzn`, not
+-- `Trvrsbl`.
 instance F.Foldable (ISet Frzn) where
   foldr fn zer (ISet (WrapLVar lv)) =
     unsafeDupablePerformIO $
     SLM.foldlWithKey (\ a k _v -> return (fn k a))
                            zer (L.state lv)
 
--- | Of course, the stronger `Trvrsbl` state is still fine for folding.
+-- Of course, the stronger `Trvrsbl` state is still fine for folding.
 instance F.Foldable (ISet Trvrsbl) where
   foldr fn zer mp = F.foldr fn zer (castFrzn mp)
 
@@ -141,16 +143,16 @@
 defaultLevels :: Int
 defaultLevels = 8
 
--- | Create a new, empty, monotonically growing 'ISet'.
+-- | Create a new, empty, monotonically growing set.
 newEmptySet :: Ord a => Par d s (ISet s a)
 newEmptySet = newEmptySet_ defaultLevels
 
--- | Tuning: Create a new, empty, monotonically growing 'ISet', with the given number
--- of skiplist levels.
+-- | Tuning: Create a new, empty, monotonically growing set, with the given number
+-- of skip list levels.
 newEmptySet_ :: Ord a => Int -> Par d s (ISet s a)
 newEmptySet_ n = fmap (ISet . WrapLVar) $ WrapPar $ newLV $ SLM.newSLMap n
 
--- | Create a new set populated with initial elements.
+-- | Create a new `ISet` populated with initial elements.
 newSet :: Ord a => S.Set a -> Par d s (ISet s a)
 newSet set = 
  fmap (ISet . WrapLVar) $ WrapPar $ newLV $ do
@@ -180,10 +182,8 @@
 -- Quasi-deterministic ops:
 --------------------------------------------------------------------------------
 
-type QPar = Par QuasiDet 
-
 -- | Freeze an 'ISet' after a specified callback/handler is done running.  This
--- differs from withCallbacksThenFreeze by not taking an additional action to run in
+-- differs from `withCallbacksThenFreeze` by not taking an additional action to run in
 -- the context of the handlers.
 --
 --    (@'freezeSetAfter' 's' 'f' == 'withCallbacksThenFreeze' 's' 'f' 'return ()' @)
@@ -229,7 +229,7 @@
         SLM.foldlWithKey (\() v () -> forkHP hp $ callb v) () slm
 
 -- | Add an (asynchronous) callback that listens for all new elements added to
--- the set
+-- the set.
 forEach :: ISet s a -> (a -> Par d s ()) -> Par d s ()
 forEach = forEachHP Nothing
 
@@ -252,7 +252,7 @@
     deltaThresh e2 | e2 == elm = return $ Just ()
                    | otherwise = return Nothing
 
--- | Wait on the SIZE of the set, not its contents.
+-- | Wait on the /size/ of the set, not its contents.
 waitSize :: Int -> ISet s a -> Par d s ()
 waitSize !sz (ISet (WrapLVar lv)) = WrapPar$
     getLV lv globalThresh deltaThresh
@@ -275,11 +275,11 @@
 copy :: Ord a => ISet s a -> Par d s (ISet s a)
 copy = traverseSet return 
 
--- | Establish monotonic map between the input and output sets.
+-- | Establish a monotonic map between the input and output sets.
 traverseSet :: Ord b => (a -> Par d s b) -> ISet s a -> Par d s (ISet s b)
 traverseSet f s = traverseSetHP Nothing f s
 
--- | An imperative-style, inplace version of 'traverseSet' that takes the output set
+-- | An imperative-style, in-place version of 'traverseSet' that takes the output set
 -- as an argument.
 traverseSet_ :: Ord b => (a -> Par d s b) -> ISet s a -> ISet s b -> Par d s ()
 traverseSet_ f s o = traverseSetHP_ Nothing f s o
@@ -292,11 +292,11 @@
 intersection :: Ord a => ISet s a -> ISet s a -> Par d s (ISet s a)
 intersection = intersectionHP Nothing
 
--- | Cartesian product of two sets.
+-- | Take the cartesian product of two sets.
 cartesianProd :: (Ord a, Ord b) => ISet s a -> ISet s b -> Par d s (ISet s (a,b))
 cartesianProd s1 s2 = cartesianProdHP Nothing s1 s2 
   
--- | Takes the cartesian product of several sets.
+-- | Take the cartesian product of several sets.
 cartesianProds :: Ord a => [ISet s a] -> Par d s (ISet s [a])
 cartesianProds ls = cartesianProdsHP Nothing ls
 
@@ -304,7 +304,7 @@
 -- Alternate versions of functions that EXPOSE the HandlerPools
 --------------------------------------------------------------------------------
 
--- | Variant that optionally ties the handlers to a pool.
+-- | Variant of `traverseSet` that optionally ties the handlers to a pool.
 traverseSetHP :: Ord b => Maybe HandlerPool -> (a -> Par d s b) -> ISet s a ->
                  Par d s (ISet s b)
 traverseSetHP mh fn set = do
@@ -312,7 +312,7 @@
   traverseSetHP_ mh fn set os  
   return os
 
--- | Variant that optionally ties the handlers to a pool.
+-- | Variant of `traverseSet_` that optionally ties the handlers to a pool.
 traverseSetHP_ :: Ord b => Maybe HandlerPool -> (a -> Par d s b) -> ISet s a -> ISet s b ->
                   Par d s ()
 traverseSetHP_ mh fn set os = do
diff --git a/lvish.cabal b/lvish.cabal
--- a/lvish.cabal
+++ b/lvish.cabal
@@ -10,11 +10,12 @@
 -- PVP summary:      +-+------- breaking API changes
 --                   | | +----- non-breaking API additions
 --                   | | | +--- code changes with no API change
-version:             1.0
+version:             1.0.0.2
 
 -- Changelog:
--- 0.2 -- switch SLMap over to O(1) freeze
-
+-- 0.2     -- switch SLMap over to O(1) freeze
+-- 1.0     -- initial public release
+-- 1.0.0.2 -- minor docs polishing
 
 synopsis:  Parallel scheduler, LVar data structures, and infrastructure to build more.
 
@@ -24,10 +25,14 @@
   .
   As a starting point, look at "Control.LVish", as well as one of these papers:
   .
-    * /LVars: lattice-based data structures for deterministic parallelism/ (<http://dl.acm.org/citation.cfm?id=2502326>).
+    * FHPC 2013: /LVars: lattice-based data structures for deterministic parallelism/ (<http://dl.acm.org/citation.cfm?id=2502326>).
   .
-    * /Freeze after handling: quasi-deterministic programming with LVars/ (<http://www.cs.indiana.edu/~lkuper/papers/2013-lvish-draft.pdf>).
 
+    * POPL 2014: /Freeze after writing: quasi-deterministic programming with LVars/ (<http://www.cs.indiana.edu/~lkuper/papers/2013-lvish-draft.pdf>).
+  . 
+  If the haddocks are not building, here is a mirror:
+  <http://www.cs.indiana.edu/~rrnewton/haddock/lvish/>
+
 license:             BSD3
 license-file:        LICENSE
 author:              Aaron Turon, Lindsey Kuper, Ryan Newton
@@ -62,6 +67,12 @@
 
 --------------------------------------------------------------------------------
 library
+  Source-repository head
+    type:     git
+    location: https://github.com/iu-parfunc/lvars
+    subdir:   haskell/lvish
+    tag:      release-lvish-1.0.0.2
+
   -- Modules exported by the library.
   exposed-modules:
                     ------------- End user modules ------------
@@ -105,13 +116,14 @@
   build-depends: base ==4.6.*, deepseq ==1.3.*, containers ==0.5.*, lattices ==1.2.*, 
                  split ==0.2.*, bytestring ==0.10.*, time ==1.4.*, rdtsc ==1.3.*, vector ==0.10.*, 
                  parallel ==3.2.*, async ==2.0.*,
-                 atomic-primops, hashable, transformers, random, chaselev-deque, bits-atomic, missing-foreign,
+                 atomic-primops, hashable, transformers, random, 
+                 chaselev-deque, 
+                 bits-atomic, missing-foreign,
                  ghc-prim
   -- TEMP:
   build-depends: HUnit, test-framework, test-framework-hunit, test-framework-th,
                  bytestring-mmap
-  -- Actually -threaded won't do anything for a library, this is just a reminder:
-  ghc-options: -O2 -threaded -rtsopts
+  ghc-options: -O2 -rtsopts
   if flag(abstract-par) 
     cpp-options: -DUSE_ABSTRACT_PAR
     build-depends:  abstract-par >=0.4
