Ambiguity and context-dependent overloading

This paper discusses ambiguity in the context of languages that support context-dependent overloading, such as Haskell. A type system for a Haskell-like programming language that supports context-dependent overloading and follow the Hindley-Milner approach of providing context-free type instantiation, allows distinct derivations of the same type for ambiguous expressions. Such expressions are usually rejected by the type inference algorithm, which is thus not complete with respect to the type system. Also, Haskell’s open world approach considers a definition of ambiguity that does not conform to the existence of two or more distinct type system derivations for the same type. The article presents an alternative approach, where the standard definition of ambiguity is followed. A type system is presented that allows only context-dependent type instantiation, enabling only one type to be derivable for each expression in a given typing context: the type of an expression can be instantiated only if required by the program context where the expression occurs. We define a notion of greatest instance type for each occurrence of an expression, which is used in the definition of a standard dictionary-passing semantics for core Haskell based on type system derivations, for which coherence is trivial. Type soundness is obtained as a result of disallowing all ambiguous expressions and all expressions involving unsatisfiability in the use of overloaded names. Following the standard definition of ambiguity, satisfiability is tested—i.e., “the world is closed” —if only if overloading is (or should have been) resolved, that is, if and only if there exist unreachable variables in the constraints on types of expressions. Nowadays, satisfiability is tested in Haskell, in the presence of multi-parameter type classes, only upon the presence of functional dependencies or an alternative mechanism that specifies conditions for closing the world, and that may happen when there exist or not unreachable type variables in constraints. The satisfiability trigger condition is then given automatically, by the existence of unreachable variables in constraints, and does not need to be specified by programmers, using an extra mechanism.


Introduction
Parametric polymorphism allows instantiation of quantified variables α, in quantified types ∀α.σ, to all types [α := τ ]σ, that is, every type generated from σ by replacing free occurrences of type variable α in σ by an arbitrary type τ (the notion of free and bound variables is well known; see, e.g., [1,2]).Type τ is restricted in ML and Haskell to be any simple (unquantified) type, characterizing an important restriction of the so-called ML-style or Let-polymorphism.Constrained polymorphism allows instantiation of quantified type variables to be restricted to some, instead of being possible to occur for all simple types.The set of types to which a type variable can be instantiated depends on the types of definitions of overloaded names (or symbols) that exist in the relevant context.
Constrained polymorphism is supported in programming languages like Haskell by context-dependent overloading, which is a form of overloading in which the decision of which definition of an overloaded name is used depends on the context where this name is used.In other words, in any expression f e, the decision of which f is called or which e is applied depends not only on the types of f and e, but also on the context in which f e is used.
In such systems, ambiguity becomes a concern.The existence of ambiguous expressions prevents a coherent semantics to be defined by induction on type system derivations, where coherence establishes a single well-defined meaning for each expression.That is, a coherent semantics is such that, for any well-typed expression e: "if and are derivations of typing formulas e : σ and e : σ, respectively, and and give the same type to every x free in e, then where the meanings are defined using and , respectively."[1] An expression e of type σ for which there exist two distinct syntax-driven derivations ( and , for which distinct semantic values might be assigned to e) is called ambiguous, in a typing context that gives the same type to every x free in e as and .The restriction to syntax-driven derivations avoids differences that are neither related to the syntax of terms nor to the used typing information.
A type system for a Haskell-like programming language, that supports context-dependent overloading and follow the Hindley-Milner approach of providing context-free type instantiation, allows distinct derivations of the same type to be derivable for some expressions, which are then ambiguous.Such expressions are usually rejected by the type inference algorithm, which becomes then not complete with respect to the type system.This article addresses this issue by considering an alternative approach that disallows contextindependent type instantiation for type systems that support context-dependent overloading.
Ambiguity in the presence of context-dependent overloading is discussed, in the traditional way of allowing contextindependent type instantiation and by characterizing ambiguity as a syntactic property of constrained types, by Jones [3] and by Stuckey and Sulzmann [4].The unfortunate lack of completeness of type inference algorithms and incoherence of semantics definitions are reported by Vytiniotis et al. [5].Faxén [7] expresses wishes for a deterministic way to outlaw ambiguity in the type system, at the same time recognizing the need for the description to remain more abstract than that obtained directly from the type inference algorithm.In our view, the abstract view is provided by the fact that the type system is defined in terms of relations, not functions, and the type inference algorithm can be obtained by transforming these relations into functions.
presents an alternative approach to type inference in the presence of Haskell-style constrained type classes.The key feature of the type system is that it allows only contextdependent instantiation, so an expression, if typeable, has a unique type derivation.We can therefore define the semantics over these type-derivations, thereby ensuring coherence.The declarativeness of the specification of the type system is, in our view, equivalent to it being given by a relation (between typing contexts, expressions and polymorphic constrained types), not as a function.In order to transform it into a type inference algorithm, it suffices to transform all used relations (used in the definition of such a relation) into functions.
The fact that the type system allows only contextdependent type instantiation eliminates the problem of the lack of principal type caused by user-specified type signatures, reported by Faxén [6,Sect. 3].
The article also presents an alternative approach for dealing with ambiguity in the context of Haskell's open world approach.In Haskell, an expression is considered as ambiguous without conformance to the existence of two or more distinct derivations of the same type for this expression.Ambiguity is considered in Haskell as a syntactic condition on type expressions, conflicting with the standard semantically-related definition given above.This occurs because Haskell uses an open world approach to overloading, according to which new definitions of overloaded names might be inserted without altering the typability of expressions.This paper presents an alternative approach where there is no conflict with the standard semantic definition of ambiguity, built upon the distinction between ambiguity and resolved overloading.In this approach, the possibility of inserting new definitions (i.e., openness of the world) is restricted to cases when overloading is not resolved.When overloading is resolved, existing definitions of overloaded names are then considered, in order to check ambiguity.
With the purpose of clarifying these issues, namely that ambiguity is distinct from resolved overloading, and that ambiguity should be considered if and only if (or when and only when) overloading is resolved, we present and discuss examples in the next section which consider ambiguity in the presence of multi-parameter type classes, where ambiguity becomes more relevant.In Sect. 3 we define a mini-language called core Haskell that supports contextdependent overloading and multi-parameter type classes, and define a type system that avoids ambiguous expressions to be well-typed.In Sect. 4 we define a semantics by induction on core Haskell's type system derivations.Section 5 concludes.In Haskell+MPTC, expression f o is not ambiguous, because overloadings of f and o have not been resolved.

Ambiguity and overloading resolution
The main purpose of this example is to show that we can have, if context-independent type instantiation is allowed, two derivations of the same type (Float) with distinct semantics, for an expression that is not ambiguous: one derivation for f of type I nt → Float, and another for f of type Float → Float.
This example also illustrates that this occurs despite the fact that f o has type (F a b, O a) ⇒ b, where type variable a occurs in the constraints but not in the simple type (b), considering that f is a member of type class F with two parameters a, b, having (implicitly quantifiable) type F a b ⇒ a → b, and o is a member of type class O with (implicitly quantifiable) type O a ⇒ a.
In Haskell, a syntactic condition on type expressions that characterizes overloading whose resolution cannot be further deferred (i.e., must have occurred), which we call overloading resolution condition characterizes also "type ambiguity".It is a syntactic condition, that conflicts with the standard definition of ambiguity, based on the existence of distinct type system derivations of the same type for an expression.
The overloading resolution condition used in Haskell (Haskell 98 or Haskell 2010), which supports only single parameter type classes, has been changed in Haskell implementations that support multi-parameter type classes.In the case of single parameter type classes, the overloading resolution condition for constrained type P ⇒ τ is simply tv(P) ⊆ tv(τ ) (i.e., there is a type variable that occurs in P but not in τ ).In the case of multi-parameter type classes, the condition considers so-called reachable type variables.A type variable occurring in P is reachable, from a set of type variables tv(τ ) in a constrained type P ⇒ τ, if it occurs in τ or if it occurs in a constraint in P where another reachable type variable occurs (if a type variable is not reachable, it is, of course, unreachable).In the example above, type variable a in (F a b, O a) ⇒ b occurs in the set of constraints ({F a b, O a}) but not in the simple type (b).This does not characterize that overloading must have been resolved, because type variable a is reachable, since it occurs in constraint F a b, where another reachable type variable (b) occurs.This idea, used nowadays in Haskell implementations that support multi-parameter type classes, appeared firstly in [8], as far as we know.
If used in a program context that requires f o to be of type I nt-in an expression such as, for example, f o + (1::Int) -overloadings of f and o in f o are resolved, with f and o having types I nt, → I nt and I nt, respectively.
If used in a program context that requires f o to be of type Float, overloadings of f and o in f o cannot be resolved, and then, in the context of this example, we have ambiguity.If used in a program context that requires f o to be of a type τ distinct from I nt and Float, overloadings of f and o in f o cannot be resolved either, but we have then, in the context of this example, unsatisfiability, since we cannot have a derivation of such type τ for e in this context.
Example 2 Let e 0 be the expression show.read(where "." denotes function composition, so e 0 can be written also as (λx -> show(readx)).In Haskell, this expression is considered as ambiguous, irrespective of the context in which it occurs (see, e.g., [3,5]).
When However, if e 0 is used in a context with a single instance for both show and read, say show:Int → Stringand read: String → Int, then there is no ambiguity, since there exists only one derivation for e 0 of type String→ String.If there are no definitions of show or no definitions of read in the typing context, again there is an error, but of unsatisfiability, not ambiguity.
The expression is ambiguous (according to the standard definition), if and only if there exist two or more distinct type system derivations-each given (==) distinct types, say In Haskell this is not possible without overlapping instances or without hiding the Haskell prelude definition of (==) for lists.
Example 4 Let e 1 be the expression fst (True, o), where o is overloaded (or is an expression with a constrained type).This expression has type Bool.Overloading of o is not resolved, but it need not be for e 1 to be well-typed (and evaluated, as equal to True).
The ambiguity or not of e 1 in GHC [9] and its interactive interpreter counterpart GHCi, the most widely used implementations of Haskell, depends on which o is used and on whether the compiler, GHC, or an interactive session of the interpreter, GHCi, is used.In GHC and in non-interactive sessions of GHCi, e 1 is not well-typed.In an interactive session (i.e., if it is typed at the GHCi's prompt), if o has only constraints on some particular type classes (namely Eq, Ord, Num and Show), it has type Bool.

Core language
We use a context-free syntax of core Has-kell expressions, given in Fig. 1, where meta-variable x represents a variable.We use meta-variables x, y, z for variables, and e for expressions, possibly primed or subscripted.The language of terms is called here core Has-kell (not core ML) because expressions occur in a global context with information about overloaded symbols.
A context-free syntax of constrained types is presented in Fig. 2, where meta-variable usage is also indicated.For simplicity and following common practice, kinds are not considered in type expressions and type expressions which are not simple types are not explicitly distinguished from simple types.Also, type expression variables are called simply type variables.x denotes the sequence x 1 , . . ., x n , where n ≥ 0. When used in the context of a set, it denotes the corresponding set of elements in the sequence ({x 1 , . . ., x n }).
We assume for simplicity that overloaded definitions are predefined, and form a global overloading environment (cf., e.g., [3,10,11]).The global overloading environment is always a fixed set of closed constraints, being an unchanged part of typing contexts.We write to mean a fixed, global overloading environment that is assumed to be a part of typing context .
A substitution, denoted by meta-variable S, possibly primed or subscripted, is a function from type variables to simple type expressions.The identity substitution is denoted by id.Sσ represents the capture-free operation of substituting S(α) for each free occurrence of type variable α in σ.Sθ and sets of types and constraints are defined analogously.Symbol • denotes function composition, and We use this function updating notation for other functions other than substitutions.Also, A substitution S is said to be more general than a substitution S , written S ≤ S , if there is a substitution S 1 such that S = S 1 • S.
We use: A type system for core Haskell is presented in Fig. 3, using rules of the form e : (φ, S), which means that e has type In general, we have the following, where a program context C[e] is an expression which has e as a subexpression, and orderings on types and typing contexts are as defined in Fig. 4. For each expression e, there is a unique type φ derivable for e in a typing context .However, expression e can have though a set of instance-types, in program contexts that require instantiation of φ in (in fact, in all typing contexts such that ≤ , cf.Theorem 1).Consider the following example where B and C represents abbreviations of Bool and Char, respectively.Instance-types are formally defined as follows.

Definition 1
Given expression e and typing context , we have that S φ is an instance-type for e in if e : (φ, S) and C[e] : (φ , S ) hold, where ≤ .Furthermore, S φ is a greatest (most specific) instance-type for an occurrence of e in if S φ is an instance-type for e in and there is no instance-type S 1 φ distinct from S φ for e in such that S 1 ≤ S.
Distinct occurrences of an expression can have distinct greatest instance-types.For example, the instance-types given in Example 6 are greatest instance-types for the corresponding occurrence of (==).
mgu is the most general unifier relation [12][13][14]: mgu(T , S) is defined to hold between a set of pairs of simple types or a set of constraints T and a substitution S if the following hold: i) Sτ = Sτ for every (τ, τ ) ∈ T (analogously, Sπ = Sπ for every (π, π ) ∈ T ), and if S is a unifier of T , then S ≤ S.
When the parameter of mgu is a singleton set, following common practice it is written simply as an equality; e.g., mgu(π = π , S) is written instead of using a set notation like this: The set of constraints P| * V denotes the subset of constraints of P with reachable type variables with respect to the set of type variables V [8].A type variable α ∈ P is called reachable with respect to a set of type variables V if α ∈ V or α ∈ tv(π) and there exists β ∈ tv(π) such that β is reachable (otherwise it is an unreachable type variable).Reachability is considered always with respect to V = tv(τ ) for a constraint set P that occurs on a constrained type P ⇒ τ.For example, type variables a, b are reachable and c is unreachable in constraint set {C a b, D c} of constrained type {C a b, D c} ⇒ a. Reachability is defined in Fig. 5.
Given any set of type variables V, the constraints of a constraint set P can be partitioned into two disjoint subsets P| * V and P − P| * V , the first containing constraints with at least one reachable type variable and the second constraints with only unreachable type variables.
P ⊕ V Q denotes the constraint set obtained by adding from Q only constraints with type variables reachable from V, i.e., P ⊕ V Q = P ∪ Q| * V [8,15].This takes into account that, in an application of a function with type, say τ 1 → τ, to an expression with type P ⇒ τ 1 , it is not always adequate to include in the constraint set of the result all constraints from Q.This occurs because constraints in P may refer to disregarded, non-selected parts of the argument.Consider for example expression f st(True, o) (cf., Sect.2), where o has any type with non-empty constraints.The type of this expression should be Bool, that is, constraints on the type of o should not be part of the set of constraints on the type of f st(True, o).

Fig. 5 Constraints reachable from a set of type variables
Relation > > is a simplification relation on constraints, defined as a composition of improvement and context reduction, defined respectively in Sects.3.3 and 3.4.Firstly, the more basic relations of entailment and satisfiability are defined, in Sects.3.1 and 3.2, respectively, which are used in the definitions of improvement and context reduction.
Q u in rule (APP) represents the set of constraints with unreachable type variables (subscript u in Q u is an abbreviation of unreachable).The side-condition of rule APP expresses that Q u should be empty.An empty set of constraints Q u is obtained after checking satisfiability on the set of constraints P u , if P u has unreachable variables, and after removing these constraints with unreachable variables, by context reduction, if there exists a single satisfying solution for such constraints (cf., Definition of > > in Fig. 6).
The article proposes to treat ambiguity by following a standard definition of ambiguity, that consists in: test satisfiability (i.e., "close the world") if overloading is resolved (or should have been resolved), that is, if there exist unreachable variables in the constraints.Nowadays, satisfiability is tested in Haskell, in the presence of multi-parameter type classes, only upon the presence of functional dependencies (or a similar mechanism), that closes the world when there exist or not unreachable type variables.Our treatment of ambiguity thus restricts the cases where satisfiabilty is tested, in case, say, a mechanism such as that of functional dependencies is used, and allows to avoid the use of such mechanism (of functional dependencies, or a similar one).In the latter case, the satisfiability trigger condition becomes the existence of unreachable variables, which may then be instantiated if there exists a single satisfying substitution.
The type system uses relations (mgu, gen, > > ).The facts that it is syntax-directed and type instantiation occurs only if required by a program context allow a sound and complete type inference algorithm to be obtained by transforming these relations into computable functions.
The fact that the type system does not allow context-free type instantiation and allow the derivation of a single type for an expression in a given typing context makes it look closer to a type inference algorithm.Context-dependent notions of instance-types and most specific instance-type for each occurrence of an expression, in a given typing context, are introduced and used in the paper, instead of the standard context-independent notion of principal type.
Typability of function application f e in this type system considers f e to be well-typed, where f has type τ 1 and e has type τ 2 , if there exists types τ → τ and τ that are respective subtypes of τ 1 and τ 2 , where subtyping is simply a matching relation, as defined in Fig. 4. The property that a set of constraints P can be proven from (are entailed by) constraints in an overloading environment , written as P, is defined in Fig. 7. Following [11,16], entailment is obtained from closed constraints only, contained in a fixed set of constraints .

Satisfiability
Following [17], P is used to denote the set of satisfiable instances of constraint set P with respect to : Equality of constraint sets is considered modulo type variable renaming.That is, constraint sets P, Q are also equal if there exists a renaming substitution S that can be applied to P to make S P and Q equal.S is a renaming substitution if for all α ∈ dom(S) we have that S(α) = β, for some type variable β ∈ dom(S).
If S P ∈ P then S is called a satisfying substitution for P.
Constraint set satisfiability is in general an undecidable problem [18].It is restricted and redefined here by using a constraint-head-value finite function, in order to obtain decidability, as described below.
Constraint set satisfiability and simplification both use the same termination criterion, which is based on a measure of the sizes of types in type constraints, given the the constrainthead-value function.The sequence of constraints that unify with a constraint axiom in recursive calls of the function that checks satisfiability or simplification of a type constraint is such that either the sizes of types of each constraint in this sequence is decreasing or there exists at least one type parameter position with decreasing size.
Constraint set satisfiability is defined so that we can obtain a sound and complete type inference algorithm, by just transforming the relations defined in the type system into functions.
The definition of the constraint-head-value function is based on the use of a constraint value ν(π) that gives the number of occurrences of type variables and type constructors in π, defined as follows: Consider computation of satisfiability of a given constraint set P with respect to constraint axioms .Consider that, for checking satisfiability of a constraint π ∈ P, a constraint π unifies with the head of constraint ∀ α.P 0 ⇒ π 0 ∈ , with unifying substitution S, and suppose also that satisfiability of π requires also that some constraint π 1 unifies with π 0 , giving corresponding unifying substitution S 1 .We require the following in order for satisfiability of π to hold: 1. ν(Sπ ) is less than ν(S 1 π 1 ) or, if ν(Sπ ) = ν(S 1 π 1 ), then Sπ = π , for any π that has the same constraint value as π and unification with π 0 is required for satisfiability of π to hold, or 2. Sπ is such that there is a type argument position 0 ≤ i ≤ n such that the number of type variables and constructors, in this argument position, of constraints that unify with π 0 is always decreasing.
Decidability is guaranteed by defining the operation of updating (π 0 ) = (I, ), denoted by [π 0 , π], as follows, where where The set of satisfying substitutions for constraint set P with respect to the set of constraint axioms is given by S, such that P , 0 sats S holds, as defined in Fig. 8.The following examples illustrate the definition of constraint set satisfiability as defined in Fig. 8. Let (π).I and (π).denote the first and second components of (π), respectively.
The following illustrates a case of satisfiability involving a constraint π that unifies with a constraint head π 0 such that ν(π ) is greater than the upper bound associated to π 0 , which is the first component of (π 0 ).I.
sats S 0 where 1 = 0 [π 0 , π], which implies that 1 (π 0 ).I = (5, 1, 4); then: which is equal to the first component of 1 (π 0 ).I, and π 1 is not in 1 (π 0 )., we obtain that S 2 = {id} and π is thus satisfiable (since Since satisfiability of type class constraints is in general undecidable [18], there exist satisfiable instances which are considered to be unsatisfiable according to the definition of Fig. 8. Examples can be constructed by encoding instances of solvable post correspondence problems by means of constraint set satisfiability, using Smith's scheme [18]. To prove that satisfiability as defined in Fig. 8 is decidable, consider that there exist finitely many constraints in , and that, for any constraint π that unifies with π 0 , we have, by the definition of [π 0 , π], that (π 0 ) is updated so as to include a new value in its second component (otherwise [π 0 , π] = Fail and satisfiability yields ∅ as the set of satisfying solutions for the original constraint).The conclusion follows from the fact that (π 0 ) can have only finitely many distinct values, for any π 0 .

Improvement
Improvement is a satisfiability preserving relation: improvement of constraint set P is the process of finding a least general substitution S such that S P preserves the set of satisfiable instances of P [3].
In this paper, improvement is used to remove unreachable type variables for resolving overloading, when overloading resolution cannot be further deferred, and for detecting ambiguity or unsatisfiability, if unreachable type variables cannot be removed (that is, overloading resolution is not possible).For any constrained type P ⇒ τ, improvement is tested only upon the presence of unreachable type variables, that is, if If the set S of satisfiable instances of P u has more than one element, we have ambiguity; if S is empty, we have unsatisfiability; otherwise, if S is a singleton {S}, then P is improved to S P, which can is then reduced to a set of constraints without unreachable type variables (that is, the set of constraints in S P u can be removed, since overloading is resolved).
Improvement is defined in Fig. 9, where 0 is as defined in Sect.3.2, page 16.Informally speaking, context reduction is a process that reduces a constraint π into Q if there is a matching instance for π in , that is, there exists (∀ α.P ⇒ π ) ∈ such that Sπ = π, for some S, and S P reduces to Q.If there is no matching instance for π or no reduction of S P is possible, then π reduces to itself.Note that constraint sets can be reduced into larger constraint sets.
As an example of a context reduction, consider an instance declaration that introduces ∀a.Eq a ⇒ Eq [a] in ; then Eq [a] is reduced to Eq a.
Context reduction can also occur due to the presence of superclass class declarations, but we only consider the case of instance declarations in this paper, which is the more complex process.The treatment of reducing constraints due to the existence of superclasses is standard; see, e.g., [3,7,10].
Context reduction uses matches, defined as follows: matches π, ( , ), ) holds if where mgm is analogous to mgu but denotes the most general matching substitution, instead of the most general unifier.The third parameter of matches is either empty or a singleton set, since overlapping instances [19] are not considered.
Context reduction, defined in Fig. 10, uses rules of the form P , red Q; , meaning that either P reduces to Q under the set of closed constraints and least constraint value function , causing to be updated to , or P ,Fail red P; Fail.
Failure implies that a constraint set is updated to itself.The least constraint value function is used as in the definition of sats to guarantee that context reduction is a decidable relation.
An empty constraint set reduces to itself (RED 0 ).Rule (CONJ) specifies that constraint set simplification works, unlike con-Fig.10 Context reduction straint set satisfiability, by performing a union of the result of simplifying each constraint in the constraint set, separately.
To see that a rule similar to (CONJ) cannot be used in the case of constraint set satisfiability, consider a simple example, of satisfiability of P = {C a, D a} in = {C Int, C Bool, D Int, D Char}.The results of computing satisfiability of P yields a single substitution where a maps to Int, not the union of computing satisfiability for C a and D a separately.
Rule (INST) specifies that if there exists a constraint axiom ∀ α.P ⇒ C τ , such that C τ matches with an input constraint π, then π reduces to any constraint set Q that P reduces to.
Rules (STOP 0 ) and (STOP) deal with failure due to updating of the constraint-head-value function.

Semantics
A type class declaration defines overloaded names, also called class members, with corresponding types, and an instance declaration gives a value for each class member, referred to as a member value (sometimes also referred to in the literature as a "member function").
The semantics of core Haskell, given in Fig. 11, is based on the application of (so-called) dictionaries to overloaded names a standard core Haskell semantics [3,10,20].A dictionary is a tuple that corresponds to an instance declaration, and contains values that correspond to the definitions given in the instance declaration for each class member.A dictionary of a superclass contains also a pointer to a dictionary of each of its subclasses, but the treatment of superclasses is standard and is omitted in this paper (see, e.g., [3,7,10]).
Figure 11 defines the semantics of core Haskell by induction on type system rules, with greatest instance-types of variables explicitly annotated, that is, typing formulas for variables have the form x :: φ where φ is the greatest instance-type of this occurrence of x in typing context (cf.Definition 1).The translation of the types of expressions are also defined in Fig. 11.
For each class declaration class P ⇒ α where x :: τ , a sequence of selection functions is generated, one for each overloaded name in x.The selection function corresponding to x i simply selects the i-th component of the tuple parameter (…, x i ,…) (if n = 1, selection is done by the identity function).
For example, class Eq generates a pair of selection functions (==) and (/=), defined as equal to fst and snd.Module scope visibility rules of these generated names are not considered in this paper.See also Example 11 below.Let P denote a sequence of constraints in P in a standard, say lexicographical order.
Each instance declaration instance P ⇒ π where x = e of a class C generates a dictionary d π .Each component in d π is a function that takes one dictionary for each constraint in the (possibly empty) sequence P and yields the translation of e i , the value bound by x i in the instance declaration.The instance declaration makes values η(Sπ) and η(x i , Sτ i ) to be equal to d π , for all substitutions S, where τ i is the simple type in the type of x i .
Let η , where P = {π 1 , . . ., π n }. vSeq(P) denotes a sequence of fresh variables v i , one for each π i in the sequence P. mgu I is a functional counterpart of the most general unifier relation (mgu).
We have that η(x, P ⇒ τ, ) gives the semantics of possibly overloaded name x, with instance-type P ⇒ τ and quantified type σ ; η is overloaded to be used also on unqualified constraints (as in η(π)) and to yield dictionaries (as in η(x, τ )).In the translation, x represents a selection function, η(x, τ ) a dictionary, and w a sequence of arguments of the selected function, where arguments are themselves dictionaries: Theorem 2 For any derivations , of typing formulas e : φ and e : φ, respectively, where and give the same type to every x free in e, we have where the meanings are defined using and , respectively.
Proof Since and give the same type to every x free in e and the type system rules are syntax-directed, and are the same.

Example 11
The of the first occurrence of teq in line (1) above is equal to teq d T Eq L v 1 v 2 , where teq's translation is the identity function, teq L is a function that receives the two dictionary arguments v 1 and v 2 passed to teqww and yields the translation of function teq for lists defined above.The translation is given with respect to environment η 0 † (P → v), where P = {Showa, T Eqa}, v is the sequence v 1 v 2 , and η 0 is such that η 0 (teq, τ ) = d T Eq L , where τ = [[a]] → [[a]] → (Bool, String), and d T Eq L is a dictionary with just one component teq L .
We have also that η 0 (T Eq I nt) is equal to a dictionary with just one member (say, d T Eq I nt ), and similarly for η 0 (Show I nt).The translation of the second occurrence of teq in line (1) above is equal to:

teq d T Eq L d T Eq I nt d Show I nt
Such use of dictionaries and the ensuing selection of member values at run-time can be avoided by passing values that correspond to overloaded names that are in fact used.A common case is that of a list equality function, that can receive an equality function for list elements, instead of a dictionary containing also an unused inequality function.Passing a dictionary to select at run-time the used equality function is unnecessary and inefficient.Full laziness and common subexpression elimination are techniques used to avoid repeated construction of dictionaries at run-time [3,7].This and related implementation issues are however outside of the scope of this paper and are left for further work (see also [21,22]).
Note that constraints on types of expressions are considered in the semantics only in the cases of polymorphic and constrained overloaded variables.Consider for example expression eqStar given by: let eq = λx.λy.(==) x y in eq '*' in a context where (==) has type Eq a ⇒ a → a → Bool (we have not written a simpler expression because we want to contrast the semantics of (==) with those of expressions (==)x and (==)x y); the translation of eqStar is given by: let eq = λv.λx.λy.(==) v x y in eqdict EqChar '*' We have that (==) dictEqChar (as well as eq dictE-qChar) returns a primitive equality function for characters, say primEqChar.Expression (==) is itself a function that takes a dictionary of type t and returns the equality function from that dictionary, of type t → t → Bool.The translation of each occurrence of (==) passes a pertinent dictionary value to (==) so that the type obtained is the expected type for an equality function on values of type t.Both expressions (==)x and (==)x y have also constrained types, but a dictionary is passed only in the case of (==).The semantics of an expression with a constrained type where the set of constraints is non-empty only considers this set of constraints if the expression is an overloaded variable; otherwise constraints are disregarded in the semantics.Furthermore, since each occurrence of an overloaded variable has a translation that is the application of pertinent dictionary values to that variable, translation of types with constraints are never input or output values of the translation function (see Fig. 11).
Type soundness follows directly from the fact that if [[ e : P ⇒ τ ]]η = e : τ holds or, if e is a variable, if [[ x :: P ⇒ τ ]]η = e : τ holds, then e : τ is derivable, where is appropriately defined so as to remove overloading-related data .This can be done by creating dictionaries and selection functions as described above, and inserting corresponding type assumptions in .
Type soundness is obtained as a result of disallowing all ambiguous expressions and all expressions involving unsatisfiability in the use of overloaded names.For example, letting e 0 ≡ (λx − > show(readx)), we would not have a derivation of e 0 : String → String corresponding to e 0 : String → String if d Readt : String → t is not derivable, which would happen if t is a fresh type variable or t can be more than one simple type.In other words, d Readt : String → t is derivable if and only if t is a unique simple type.

Conclusion
This paper discusses ambiguity in the context of languages that support context-dependent overloading, such as Haskell.
A type system is presented that does not follow the Hindley-Milner approach of providing context-free type instantiation, as usually done in type systems for such languages.As a consequence, ambiguous expressions can be considered to be not well-typed, in conformance with type inference algorithms.
The type system does not allow context-free type instantiation and allows only a single type to be derived for an expression, in a given typing context, making it look closer and easier to be converted into a type inference algorithm.There is no notion of principal type (and thus no notion of "principal translation" of a term), in a given typing context.Related notions of instance type and most specific instance type for each occurrence of an expression, dependent on program contexts, are instead defined and used in the paper.
A semantics is defined by induction on the type system rules, for which coherence is trivial.Type soundness is obtained as a result of disallowing all ambiguous expressions and all expressions involving unsatisfiability in the use of overloaded names.
A standard definition of ambiguity is followed in the support for context-dependent overloading, where satisfiability is tested -i.e., "the world is closed"-if only if overloading is resolved (or should have been resolved), that is, if and only if there exist unreachable variables in the constraints on types of expressions.Nowadays satisfiability is tested in Haskell, in the presence of multi-parameter type classes, only upon the presence of functional dependencies or an alternative mechanism that specifies conditions for closing the world, and that may happen when there exist or not unreachable type variables in constraints.The satisfiability trigger condition is then given automatically, by the existence of unreachable variables in constraints, and does not need to be specified by programmers, using an extra mechanism.

Example 1
Consider expression f o, used in a context where f and o have the following types: f ::I nt → I nt f ::I nt → Float f ::Float → Float o::I nt o::Float In Haskell extended with multi-parameter type classes, referred to as Haskell+MPTC in the sequel, this can be achieved by considering that there exist declarations of type classes F a b and O a where f and o have been annotated in these classes with types a → b and a, respectively, and there exist also instance definitions F Int Int, F Int Float, F Float Float, O Int and O Float.

PExample 7
= {S P | S P} As an example, consider: = {∀a, b.Dab ⇒ C[a]b, D Bool[Bool]} Then, we have that C a a = C [Bool] [Bool] .Both constraints D Bool[Bool] ⇒ C [Bool] [Bool] and C [Bool] [Bool] are members of C a a (and of C [Bool] [Bool] ).A proof that {C [Bool]: [Bool]} holds can be given from the entailment rules given in Fig. 7, since this is the conclusion of rule (MP) with premises {D Bool [Bool]} and {D Bool[Bool] ⇒ C [Bool] [Bool]}, and these two premises can be derived by using rule (INST).

Fig. 11
Fig. 11 Core Haskell semantics used in a context with two or more instance definitions, of classes Show and Read, that give functions show and read types, say, show : I nt → String, show : Bool → String, read : String → I nt and read :