/// <summary> Gets the canonical signature (the constant set containing all elements allowed by the parameters) designated by the specified parameters, or created it if necessary. </summary> /// <param name="parameter"> The set of elements acceptable as argument. </param> /// <param name="result"> The set of returnable elements. </param> /// <param name="debuggingDescription"> A debugging-purpose description of this set. Specifiy null to use the default form. </param> public static Signature From(ISet parameter, ISet result, string debuggingDescription = null) { Contract.Requires(parameter != null); Contract.Requires(result != null); Contract.Requires(new[] { parameter, result }.Select(element => element.Workspace).AreEqual(ReferenceEqualityComparer)); Contract.Requires(genericSignatureDefinition.Parameter.Supersets(parameter)); Contract.Requires(genericSignatureDefinition.Result.Supersets(result)); Func<ISet, Signature> create; if (parameter as Set == null || result as Set == null) { //TODO: return signature definition if both result and parameter are unconstrained variable sets create = _ => { var potentialParameters = new[] { parameter as VariableSet, result as VariableSet }; ReadOnlyCollection<VariableSet> newParameters = potentialParameters.Where(NotNull).ToReadOnlyList(); ReadOnlyCollection<Variance> newVariances = potentialParameters.ZipWhere(signatureVariances, (p, variance) => p != null, (p, variance) => variance).ToReadOnlyList(2); return new Signature(new[] { parameter, result }.ToReadOnlyList(), newParameters, newVariances, debuggingDescription); }; } else { create = _ => new Signature(new[] { parameter, result }.ToReadOnlyList(), debuggingDescription); } return signatures.GetOrAdd(parameter, _ => new Dictionary<ISet, Signature>(interningEqualityComparer)) .GetOrAdd(result, create); }