 ;; test for homomorphism (3)
 (defspec deepfapply-homomorphism
   (prop/for-all [f (gen/elements [* +])
-                 args gen-coll-ints]
+                 args (gen/vector gen-coll-ints 1 5)]
     (let [out (apply deepfapply (build-fn args f) args)
           expected (expected-val args f)]
       (true?

    (seq? m) (seq [f])
    (map? m) {:a f}))

(def gen-coll-ints
  "Generates vector of collections of ints for testing"
  (gen/one-of
    [(gen/vector (gen/map (gen/return :a) gen/int {:min-elements 1}) 1 5)
     (gen/vector (gen/vector gen/int 1) 1 5)
     (gen/vector (gen/fmap list gen/int) 1 5)
     (gen/vector (gen/set gen/int {:min-elements 1
                                   :max-elements 1}) 1 5)
     (gen/vector (gen/fmap (fn [n]
                             (seq [n])) gen/int)
       1 5)]))

;; check for functional composition (2)
;; Just checking top level for now, nested is covered by unit tests
(defspec deepfapply-composition
  (prop/for-all [fs (gen/elements [+ *])
                 arg gen-coll-ints]
    (let [f1 (build-fn arg (partial fs 5))
          f2 (build-fn arg (partial fs 10))
          out1 (->> arg

;; 3. homomorphism
;; 4. interchange

(def gen-coll-ints
  "Generates a randomly typed collection of ints for testing"
  (gen/one-of
    [(gen/map (gen/return :a) gen/int {:min-elements 1})
     (gen/vector gen/int 1)
     (gen/fmap list gen/int)
     (gen/set gen/int {:min-elements 1
                                    :max-elements 1})
     (gen/fmap (fn [n]
                 (seq [n])) gen/int)]))

;; covers the identity law (1)
(defspec deepfapply-identity
  (prop/for-all [args gen-coll-ints]
    (let [out (deepfapply (pure args identity) args)]
      (and
        (is (= args out))))))

(defn build-fn [[m] f]
  (cond
