      (printer/indent (ansi/color (pr-str (:val problem)) :bad-value))
      (printer/indent (ansi/color (pr-pred (:pred problem) (:spec problem)) :good-pred)))))
 
-(defmethod problem-group-str :expound.problem/check-fn-failure [_type spec-name val path problems opts]
+(defmethod problem-group-str :expound.problem/check-fn-failure [_type spec-name form path problems opts]
   (s/assert ::singleton problems)
   (printer/format
    format-str
    (header-label "Function spec failed")
    (ansi/color (printer/indent (pr-str (:expound/check-fn-call (first problems)))) :bad-value)
-   (expected-str _type spec-name val path problems opts)))
-
-(defmethod expected-str :expound.problem/check-ret-failure [_type spec-name val path problems opts]
+   (expected-str _type spec-name form path problems opts)))
+
+(defmethod expected-str :expound.problem/check-ret-failure [_type spec-name form path problems opts]
   (predicate-errors problems))
 
-(defmethod problem-group-str :expound.problem/check-ret-failure [_type spec-name val path problems opts]
+(defmethod problem-group-str :expound.problem/check-ret-failure [_type spec-name form path problems opts]
   (printer/format
    "%s
 

                      (string/join ", "))
                 :good))))

(defmethod problem-group-str :expound.problem/not-in-set [type spec-name val path problems opts]
  (assert (apply = (map :val problems)) (str util/assert-message ": All values should be the same, but they are " problems))
  (format-err "Spec failed"
              type
              spec-name
              val
              path
              problems
              opts
              (expected-str type spec-name val path problems opts)))

(defmethod expected-str :expound.problem/missing-spec [_type spec-name val path problems opts]
  (str "with\n\n"
       (->> problems
            (map #(no-method spec-name val path %))
            (string/join "\n\nor with\n\n"))))

(defmethod value-str :expound.problem/missing-spec [_type spec-name val path problems opts]
  (printer/format
   "Cannot find spec for

%s"
   (show-spec-name spec-name (*value-str-fn* spec-name val path (paths/value-in val path)))))

(defmethod problem-group-str :expound.problem/missing-spec [type spec-name val path problems opts]
  (printer/format
   "%s\n\n%s\n\n%s"
   (header-label "Missing spec")
   (value-str type spec-name val path problems opts)
   (expected-str type spec-name val path problems opts)))

(defn ^:private lcs* [[x & xs] [y & ys]]
  (cond


;; FIXME - when I decide to break compatibility for value-str-fn, maybe
;; make it show conform/unformed value
(defn ^:private value-and-conformed-value [problems spec-name form path opts]
  (let [{:keys [show-conformed?]} opts
        invalid-value (if (nil? path)
                      ;; This isn't used by default
                      ;; because value-in-context will look at
                      ;; path and only print form, but anyone
                      ;; who provides their own *value-str-fn*
                      ;; could use this
                        ::no-value-found
                        (paths/value-in form path))]
    (printer/format
     "%s%s"
     (*value-str-fn* spec-name form path invalid-value)
     (if show-conformed?
       (conformed-value problems invalid-value)
       ""))))

;; TODO - rename val -> form
(defmethod value-str :default [_type spec-name form path problems opts]
  (show-spec-name spec-name (value-and-conformed-value problems spec-name form path {:show-conformed? true})))

(defn ^:private explain-missing-keys [problems]
  (let [missing-keys (map #(printer/missing-key (:pred %)) problems)]
