void ResolveTypes(IEnumerable <Module> modules, CancellationToken cancel)
        {
            var trr = new TypeResolveRec
            {
                Constraint  = s => new[] { s }, // true
                ExpTypeVars = Enumerable.Empty <Tuple <Expression, Var> >(),
            };

            trr = modules.Aggregate(trr, (mtr, m) =>
            {
                if (cancel.IsCancellationRequested)
                {
                    throw new OperationCanceledException(cancel);
                }

                return(m.Bindings.Values.Aggregate(mtr, (btr, b) =>
                {
                    if (cancel.IsCancellationRequested)
                    {
                        throw new OperationCanceledException(cancel);
                    }

                    return ResolveExpressionType(btr, b.Expression);
                }));
            });

            try
            {
                var varTypes = Goal.Eval(trr.Constraint).First();

                foreach (var expVar in trr.ExpTypeVars)
                {
                    var e = expVar.Item1;
                    var v = expVar.Item2;

                    if (varTypes.Binds(v))
                    {
                        e.ResolvedType = varTypes[v];
                    }
                    else
                    {
                        Unit.AddError(new AnalyzerError
                        {
                            ErrorNode = e.SyntaxNode,
                            Message   = string.Format(ErrorMessages.E_0015_Analyzer_UnableToInferType, ApteridError.Truncate(e.SyntaxNode.Text)),
                        });
                    }
                }
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception e)
            {
                Unit.AddError(new AnalyzerError {
                    Exception = e
                });
            }
        }
        TypeResolveRec ResolveExpressionType(TypeResolveRec tvr, Expression e)
        {
            tvr = e.Children.Aggregate(tvr, (tvrc, c) => ResolveExpressionType(tvrc, c));
            var v      = Var.NewVar();
            var result = new TypeResolveRec
            {
                Constraint  = Goal.Conj(tvr.Constraint, e.ResolveType(v)),
                ExpTypeVars = tvr.ExpTypeVars.Concat(new[] { Tuple.Create(e, v) }),
            };

            return(result);
        }