 subContext = (subs, context) ->
   newContext = newMap()
   for name, t of context.values
-    setInMap newContext, name, (subExp subs, t)
+    addToMap newContext, name, (subExp subs, t)
   newContext
 
 isTypeVariable = (name) ->
-  name.charCodeAt(0) >= 97
+  not (Array.isArray name) and name.charCodeAt(0) >= 97
 
 freshName = (nameIndex) ->
   # TODO: handle more than 27 variables


subPairs = (subs, pairs) ->
  for [t1, t2] in pairs
    [(subExp sub t1), (subExp sub t2)]

subExp = (subs, type) ->
  if Array.isArray type

        # assume if definedParams.length > 0
        argName = freshName nameIndex
        param = definedParams[0]
        context = concat context, newMapWith param.token, argName
        [s1, nextIndex, A] = infer context, body, nameIndex + 1
        [s1, nextIndex, (subExp s1, [argName, A])]

      # Call
      else if Array.isArray expression
        [op, arg] = inside expression
        # assume call.length is 2
        returnName = freshName nameIndex
        [s1, nextIndex, A] = infer context, op, nameIndex + 1
        [s2, nextIndex, B] = infer (subContext s1, context), arg, nextIndex
        log "op", s2, A, (subExp s2, A)
        log "operand", [B, returnName]
        s3 = unify (subExp s2, A), [B, returnName]
        [(concat s3, s2, s1), nextIndex, (subExp s3, returnName)]

unify = (t1, t2) ->
  unifyWith newMap(), [[t1, t2]]

unifyWith = (subs, pairs) ->
  if pairs.length is 0
