 ;; ---------------------------------------------------------------------------
 
 (defn tuple
+  "Create a generator that returns a vector, whose elements are chosen
+  from the generators in the same position.
+
+  Examples:
+
+    (def t (tuple [gen/int gen/boolean]))
+    (sample t)
+    ;; => ([1 true] [2 true] [2 false] [1 false] [0 true] [-2 false] [-6 false]
+    ;; =>  [3 true] [-4 false] [9 true]))
+  "
   [generators]
   [:gen (fn [rand-seed size]
     (vec (clojure.core/map #(call-gen % rand-seed size) generators)))])

;; ---------------------------------------------------------------------------

(defprotocol Shrink
  (shrink [this]))

(defn fmap
  "NOTE: since `gen` is a function, this is just equivalent
  to `comp`. Perhaps using fmap will be more confusing to people?"
  [f gen]
  [:gen (fn [rand-seed size]
          (f (call-gen gen rand-seed size)))])

(defn bind
  [gen k]
  [:gen (fn [rand-seed size]
          (let [value (call-gen gen rand-seed size)]
            (call-gen (k value) rand-seed size)))])

(defn return
  [val]
  [:gen (fn [rand-seed size] val)])


;; ---------------------------------------------------------------------------

(defn map
  "Create a generator that generates maps, with keys chosen from
  `ken-gen` and values chosen from `val-gen`."
  [key-gen val-gen]
  [:gen (fn [rand-seed size]
    (let [map-size (call-gen (choose 0 size) rand-seed size)
