   newContext
 
 isTypeVariable = (name) ->
-  name.charCodeAt(0) < 97 + 26
+  name.charCodeAt(0) >= 97
 
 freshName = (nameIndex) ->
   # TODO: handle more than 27 variables
   String.fromCharCode 97 + nameIndex
 
-concat = (arrays...) ->
-  [].concat arrays...
+concat = (maps...) ->
+  concated = newMap()
+  for map in maps
+    for k, v of map.values
+      addToMap concated, k, v
+  concated
 
 # mycroft = (context, node, environment) ->
 #   if node.label is 'numerical'

        returnName = freshName nameIndex
        [s1, A] = infer context, op
        [s2, B] = infer (subContext s1, context), arg
        s3 = unify (subExp s2, A), [B, returnName]
        [(concat s3, s2, s1), (subExp returnName)]

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

unifyWith = (subs, pairs) ->
  if pairs.length is 0
    subs
  else
    [[t1, t2], rest] = pairs
    if t1 is t2
      unifyWith subs, rest
    else if isTypeVariable t1
      sub = addToMap newMap(), t1, t2
      unifyWith (addToMap subs, t1, t2), subPairs rest
    else if isTypeVariable t2
      sub = addToMap newMap(), t2, t1
      unifyWith (addToMap subs, t2, t1), subPairs rest
    else if not (isTypeVariable t1) and not (isTypeVariable t2)
      [t1from, t1to] = t1
      [t2from, t2to] = t2


infer = (context, expression, nameIndex) ->
  switch expression.label
    when 'numerical' then [newMap(), 'Num']
    when 'string' then [newMap(), 'Text']
    else
      # Reference
      if isReference expression
        # TODO: replace free type variables with new unused names
        [newMap(), lookupInMap context, expression.token]
      # Lambda
      else if expression.type is 'function'
        {params, body, wheres} = fnDefinition expression
