diff --git a/Data/Repa/Scalar/Double.hs b/Data/Repa/Scalar/Double.hs
--- a/Data/Repa/Scalar/Double.hs
+++ b/Data/Repa/Scalar/Double.hs
@@ -1,5 +1,9 @@
 
 -- | Loading and storing doubles directly from/to memory buffers.
+--
+--   * Calls out to foreign load and store functions written in C and C++,
+--     so performance should be alright.
+--
 module Data.Repa.Scalar.Double
         ( -- * Loading
           loadDouble
@@ -22,6 +26,9 @@
 -- Double -----------------------------------------------------------------------------------------
 -- | Load an ASCII `Double` from a foreign buffer
 --   returning the value and number of characters read.
+--
+--   * Calls out do the stdlib `strtod` function.
+--
 loadDouble 
         :: Ptr Word8            -- ^ Buffer holding ASCII representation.
         -> Int                  -- ^ Length of buffer.
@@ -56,6 +63,9 @@
 
 -- | Store an ASCII `Double`, yielding a freshly allocated buffer
 --   and its length.
+--
+--   * Calls out to the `double-conversion` library which is binding
+--     to a C++ implementation.
 --
 --   * The value is printed as either (sign)digits.digits,
 --     or in exponential format, depending on which is shorter.
diff --git a/Data/Repa/Scalar/Int.hs b/Data/Repa/Scalar/Int.hs
--- a/Data/Repa/Scalar/Int.hs
+++ b/Data/Repa/Scalar/Int.hs
@@ -1,5 +1,10 @@
 
 -- | Loading and storing integers directly from/to memory buffers.
+--
+--   * The implementation uses native Haskell unboxed primitives. 
+--     There there should not be any significant performance penalty
+--     relative to the standard implementations in other languages (like C).
+--
 module Data.Repa.Scalar.Int
         ( -- * Reading from strings
           readInt
diff --git a/Data/Repa/Scalar/Option.hs b/Data/Repa/Scalar/Option.hs
--- a/Data/Repa/Scalar/Option.hs
+++ b/Data/Repa/Scalar/Option.hs
@@ -1,6 +1,8 @@
 
--- | Option types are synonyms for @Maybe a@, @Maybe (a, b)@ and so on, 
---   which are strict in the components.
+-- | Option types are similar to @Maybe a@, @Maybe (a, b)@ and so on, 
+--   except they are directly unpacked into the constructor and are
+--   strict in each component.
+--
 module Data.Repa.Scalar.Option
         ( -- * Single component
           Option  (..)
diff --git a/Data/Repa/Scalar/Product.hs b/Data/Repa/Scalar/Product.hs
--- a/Data/Repa/Scalar/Product.hs
+++ b/Data/Repa/Scalar/Product.hs
@@ -3,15 +3,18 @@
         ( -- * Product type
           (:*:)         (..)
         , IsProdList    (..)
+        , IsKeyValues   (..)
 
           -- * Selecting
-        , Select (..)
+        , Select        (..)
 
           -- * Discarding
-        , Discard (..), Keep(..), Drop(..)
+        , Discard       (..)
 
           -- * Masking
-        , Mask    (..))
+        , Mask          (..)
+        , Keep          (..)
+        , Drop          (..))
 where
 import Data.Repa.Scalar.Singleton.Nat
 import qualified Data.Vector.Unboxed            as U
@@ -28,9 +31,9 @@
 infixr :*:
 
 
+-- | Sequences of products that form a valid list, 
+--   using () for the nil value.
 class IsProdList p where
- -- | Check if a sequence of products forms a valid list, 
- --   using () for the nil value.
  --
  -- @
  -- isProdList (1 :*: 4 :*: 5)  ... no instance
@@ -44,17 +47,53 @@
  isProdList _ = True
  {-# INLINE isProdList #-}
 
-
 instance IsProdList fs => IsProdList (f :*: fs) where
  isProdList (_ :*: xs) = isProdList xs
  {-# INLINE isProdList #-}
 
 
+-- Key-value pairs---------------------------------------------------------------------------------
+-- | Sequences of products and tuples that form hetrogeneous key-value pairs.
+class IsKeyValues p where
+ type Keys   p 
+ type Values p 
+
+ -- | Get a cons-list of all the keys.
+ keys   :: p -> [Keys p]
+
+ -- | Get a heterogeneous product-list of all the values.
+ values :: p -> Values p
+
+
+instance IsKeyValues (k, v) where
+ type Keys   (k, v)     = k
+ type Values (k, v)     = v
+
+ keys   (k, _)          = [k]
+ {-# INLINE keys #-}
+
+ values (_, v)          = v
+ {-# INLINE values #-}
+
+
+instance (IsKeyValues p, IsKeyValues ps, Keys p ~ Keys ps)
+       => IsKeyValues (p :*: ps) where
+
+ type Keys   (p :*: ps) = Keys p
+ type Values (p :*: ps) = Values p :*: Values ps
+
+ keys   (p :*: ps)      = keys p   ++  keys ps
+ {-# INLINE keys #-}
+
+ values (p :*: ps)      = values p :*: values ps
+ {-# INLINE values #-}
+
+
 ---------------------------------------------------------------------------------------------------
 class    IsProdList t
       => Select  (n :: N) t where
  type    Select'    n        t
- -- | Return just the given field in this tuple.
+ -- | Return the element with this index from a product list.
  select ::          Nat n -> t -> Select' n t
 
 
@@ -76,7 +115,7 @@
 class    IsProdList t 
       => Discard (n :: N) t where
  type    Discard'   n        t
- -- | Discard the given field in this tuple.
+ -- | Discard the element with this index from a product list.
  discard ::         Nat n -> t -> Discard' n t
 
 
diff --git a/repa-scalar.cabal b/repa-scalar.cabal
--- a/repa-scalar.cabal
+++ b/repa-scalar.cabal
@@ -1,5 +1,5 @@
 Name:           repa-scalar
-Version:        4.2.0.3
+Version:        4.2.1.1
 License:        BSD3
 License-file:   LICENSE
 Author:         The Repa Development Team
