             [:x] [pred/required-key integer?]
             [:y] [pred/required-key integer?]}))
     
-    (fact "a line has a start and an end, which are points"
-      (subject/canonicalize type-map [:start :end]
-                            {:start (path/includes :Point)
-                             :end (path/includes :Point)})
-      => {[:start] [pred/required-key]
-          [:end] [pred/required-key]
-          [:start :x] [pred/required-key integer?]
-          [:start :y] [pred/required-key integer?]
-          [:end :x] [pred/required-key integer?]
-          [:end :y] [pred/required-key integer?]})
-    
+    (fact "subtypes"
+      (fact "making a colored point by addition"
+        (subject/canonicalize type-map (path/includes :Point) [:color] {:color string?})
+        => {[:color] [pred/required-key string?]
+            [:x] [pred/required-key integer?]
+            [:y] [pred/required-key integer?]}
+        
+        (fact "or you can just merge types"
+          (subject/canonicalize type-map (path/includes :Point) (path/includes :Colored))
+          => {[:color] [pred/required-key string?]
+              [:x] [pred/required-key integer?]
+              [:y] [pred/required-key integer?]})
+        
+        (fact "note that merging an optional type doesn't make it required"
+          (subject/canonicalize type-map (path/includes :Point) (path/includes :OptionalColored))
+          => {[:color] [string?]
+              [:x] [pred/required-key integer?]
+              [:y] [pred/required-key integer?]}))
+      
+      (fact "a line has a start and an end, which are points"
+        (subject/canonicalize type-map [:start :end]
+                              {:start (path/includes :Point)
+                               :end (path/includes :Point)})
+        => {[:start] [pred/required-key]
+            [:end] [pred/required-key]
+            [:start :x] [pred/required-key integer?]
+            [:start :y] [pred/required-key integer?]
+            [:end :x] [pred/required-key integer?]
+            [:end :y] [pred/required-key integer?]})
+      
     (fact "a figure has a color and a set of points"
       (subject/canonicalize type-map [:points]
                             {[:points ALL] (path/includes :Point)}

      => {[:points] [pred/required-key]
          [:points ALL :color] [pred/required-key string?]
          [:points ALL :x] [pred/required-key integer?]
          [:points ALL :y] [pred/required-key integer?]})))


;;;; Let us not forget the simple cases

(fact "simple maps just have their keys and values vectorized"
  (subject/canonicalize ..t.. {:a even?}) => {[:a] [even?]}
  (subject/canonicalize ..t.. {:a even?, :b even?})
  => {[:a] [even?]
      [:b] [even?]})

(fact "simple vectors"
  (subject/canonicalize ..t.. [:a :b]) => {[:a] [pred/required-key]
                                           [:b] [pred/required-key]})
  

;;;; Canonicalize - random examples, probably redundant

(fact "already vectorized keys and values are left alone if flat"
  (subject/canonicalize ..t.. {[:a] even?}) => {[:a] [even?]}
  (subject/canonicalize ..t.. {[:a] [even?]}) => {[:a] [even?]}
  (subject/canonicalize ..t.. {[:a :b] even?}) => {[:a :b] [even?]})
  
(fact "forks are allowed in vectors"
  (subject/canonicalize ..t.. {[:a [:b1 :b2]] even?})
  => {[:a :b1] [even?]

      [:a :b1 :c :d2] [even?]
      [:a :b2 :c :d1] [even?]
      [:a :b2 :c :d2] [even?]})
