   visitExpressions ast, (expression) ->
     expressions.push "#{collapse toHtml expression} :: #{highlightType expression.tea}" if expression.tea
   types: values mapMap (__ highlightType, _type), subtractMaps ctx._scope(), builtInDefinitions()
-  subs: values mapMap highlightType, ctx.substitution
+  subs: mapSub highlightType, ctx.substitution
   ast: expressions
   deferred: ctx.deferredBindings()
 


printType = (type) ->
  if type instanceof TypeVariable
    type.name
  else if type instanceof QuantifiedVar
    "#{type.var}"
  else if type instanceof TypeConstr
    type.name
  else if type instanceof TypeApp
    flattenType collectArgs type
  else if type instanceof ForAll

    else
      emptySubstitution()
  else
    unifyFail t1, t2

unifyFail = (t1, t2) ->
  substituionFail "could not unify #{(safePrintType t1)}, #{(safePrintType t2)}"

bindVariable = (variable, type) ->
  if type instanceof TypeVariable and variable.name is type.name
    emptySubstitution()
  else if inSet (findFree type), variable.name
    substituionFail "occurs check failed for #{variable.name}"
    # newMapWith variable.name, "occurs check failed"
  else if not kindsEq (kind variable), (kind type)
    # newMapWith variable.name, "kinds don't match for #{variable.name} and #{safePrintType type}"
    substituionFail "kinds don't match for #{variable.name} and #{safePrintType type}"
  else
    newSubstitution variable.name, type

# Maybe substitution if the types match
# t1 can be more general than t2
toMatchTypes = (t1, t2) ->
  substitution = matchType t1, t2
  if _notEmpty substitution.fails
    null
  else
    substitution

# Returns a substitution
matchType = (t1, t2) ->
  if t1 instanceof TypeVariable and kindsEq (kind t1), (kind t2)
    newSubstitution t1.name, t2
  else if t1 instanceof TypeConstr and t2 instanceof TypeConstr and
    t1.name is t2.name
      emptySubstitution()
