   else
     cb ast, ast.token
   return
+
+crouch = (ast, cb) ->
+  if Array.isArray ast
+    for node in ast
+      crouch node, cb
+  else
+    cb ast
+  ast
 
 inside = (node) -> node[1...-1]
 

        concreteType = lookupInMap context, expression.token
        unless concreteType
          throw new Error "Unbound variable #{expression.token}"
        [newMap(), nameIndex, concreteType]
      # Lambda
      else if expression.type is 'function'
        {params, body, wheres} = fnDefinition expression

        argName = freshName nameIndex
        param = definedParams[0]
        context = concat context, newMapWith param.token, argName
        [s1, nextIndex, body] = infer context, body, nameIndex + 1
        expression.tea = (subExp s1, [argName, body.tea])
        [s1, nextIndex, expression]

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

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