   (get x :b)
 
 
+  (= eg (fact-shape ::eg "[a] has a [b] with a [c]"))
+
   (fact (fact-shape ::eg "[a] has a [b] with a [c]") #js ["a" "b" "c"])
 
   (= x x)

  (= x (fact (id->fact-shape ::eg) #js ["a" "b" "c"]))
  (= x (fact eg #js ["a" "b" "c"]))
  (= x (->eg "a" "b" "c"))

  (fact-ixes x #js [2 1])
  )

(deftype FactShape [id madlib keys]
  Object
  (toString [this]
            (apply str (interleave madlib (map (fn [k] (str "[" (name k) "]")) keys))))
  IEquiv
  (-equiv [this other]
          (and (instance? FactShape other)
               (= id (.-id other)))))

;; if given a shape behaves like a record, otherwise behaves like a vector
(deftype Fact [shape values ^:mutable __hash]
  Object
  (toString [this]
