     if t1.types.length isnt t2.types.length
       unifyFail t1, t2
     else if _notEmpty t1.types
+      # log "matching ", (printType t1.types[0]), (printType t2.types[0])
       s1 = matchType t1.types[0], t2.types[0]
-      s2 = matchType (new Types t1.types[1...]), (new Types t2.types[1...])
+      # log "after matching", s1
+      # I will imply functional dependency of the form A a b c | a -> b c
+      s2 = mostGeneralUnifier (new Types (substituteList s1, t1.types[1...])), (new Types t2.types[1...])
       s3 = mergeSubs s1, s2
       s3 or
         unifyFail t1, t2

          (findFree currentType),
          (substituteList ctx.substitution, matched.tea.constraints)
        # log "assign type", name, (printType currentType), retainedConstraints
        ctx.assignType name,
          if polymorphic
            quantifyUnbound ctx, (addConstraints currentType, retainedConstraints)

        (list-first in)))
  """
  "(first {42 43 44})", 42

  'functional deps on function'
  """
    Map (class [m k v]
      put (fn [key value map]
        (: (Fn k v m m))))

    map-map (instance (Map (Map k v) k v)
      put (macro [key value map]
        (: (Fn k v (Map k v) (Map k v)))
        (Js.call (Js.access map "set") {key value})))

    count (macro [map]
      (: (Fn (Map k v) Num))
      (Js.access map "size"))

    magic (fn [key map]
      (put key 42 map))
  """
  "(count (magic \\C (Map)))", 1

  'nested pattern matching'
  """
