Type Inference for Multi-Parameter Type Classes
|
|
- Juniper Moore
- 6 years ago
- Views:
Transcription
1 Type Inference for Multi-Parameter Type Classes Martin Sulzmann 1 and Peter J. Stuckey 2 1 School of Computing, National University of Singapore S16 Level 5, 3 Science Drive 2, Singapore sulzmann@comp.nus.edu.sg 2 NICTA Victoria Laboratory Department of Computer Science and Software Engineering The University of Melbourne, Vic. 3010, Australia pjs@cs.mu.oz.au Abstract. We observe that the combination of multi-parameter type classes with existential types and type annotations leads to a loss of principal types. As a consequence type inference in implementations such as GHC is incomplete. This may be a surprising fact for users of these standard features. We conduct a concise investigation of the problem and are able to precisely explain why we lose principality and completeness of inference. As remedy we propose several novel inference methods to retain completeness and principality. 1 Introduction Type systems are important building tools in the design of programming languages. They are typically specified in terms of a set of typing rules which are formulated in natural deduction style. The standard approach towards establishing type soundness is to show that any well-typed program cannot go wrong at run-time. Hence, one of the first tasks of a compiler is to verify whether a program is well-typed or not. The trouble is that typing rules are often not syntax-directed. Also, we often have a choice which types to assign to variables unless we demand that the programmer supplies the compiler with this information. However, using the programming language then may become impractical. What we need is a type inference algorithm which automatically checks whether a program is well-typed and as a side-effect assigns types to program text. For programming languages based on the Hindley/Milner system [Mil78] we can typically verify that type inference is complete and the inferred type is principal [DM82]. Completeness guarantees that if the program is well-typed type inference will infer a type for the program whereas principality guarantees that any type possible given to the program can be derived from the inferred type. In this paper, we ask the question whether this happy situation will continue in case of multi-parameter type classes [JJM97], a popular extension of the Hindley/Milner system and available as part of a number of compiler systems such as GHC [GHC]. In particular, we are interested in type inference in the presence of (by now standard) features such as type annotations [OL96] and (boxed) existential types [LO94]. The surprising observation is that we lose completeness
2 and principal types as the following examples show. We will make use of Haskell syntax [Has] throughout the paper. Consider the following simple program where we make use of the combination of existential types and type classes. class Foo a b where foo::a->b->int instance Foo a Int where foo = 1 -- (F1) instance Foo a Bool where foo = 2 -- (F2) data Bar = forall b. Mk b f x z = (case z of (Mk y) -> foo y x, x == length []) We introduce a two-parameter type class Foo which comes with a method foo of type a, b.foo a b a b Bool. The two instance declarations state that Foo a Int and Foo a Bool hold for any a. The data type Bar introduces a constructor Mk whose parameter b does not appear in the result type (here Bar). Hence, we consider b as existentially quantified. Note that in the Haskell syntax these existential variables are introduced by the forall keyword. We expect function f to be well-typed. Variable x has type Int (since it is equated to the result of length :: [a] -> Int) and variable z has type Bar. The pattern variable y has type b for any b (because b is existential). Hence, foo y x gives rise to the (type class) constraint Foo b Int. According to the instance (F1) this constraint holds. Hence, we find that f has type Int->Bar->(Int,Bool). A surprising observation is that GHC fails to infer a type for the above program whereas Hugs [HUG] succeeds. Though, for the following variant f2 x z = (x == length [], case z of (Mk y) -> foo y x) GHC succeeds whereas HUGS fails. It is even getting better. GHC and Hugs both fail for the following variant f3 x z = case z of (Mk y) -> foo y x We note that similar observations can be made in case of type annotations (see Appendix C). In our system the types of constructors may be constrained by type classes. E.g., the following is accepted in our system. data Erk a = forall b. Foo a b => Mk2 a b Such an extension is known as type classes with existential types. Similarly, type classes may constrain the types in annotations. Both extensions do not complicate the type inference problem any further. Hence, we assume that both extensions are part of our formal system. For the rest of this paper we write MPTC to denote the system of multi-parameter type classes with existential types and type annotations. We conclude that type inference for MPTC turns out to be surprisingly difficult. We are not aware of any formal investigation of the MPTC type inference problem. Previous works either neglects existential types and type annotations [Jon92,Jon95], or considers the single-parameter case only [Läu96]. Here, we conduct a detailed investigation of the inference problem and propose several novel solutions. In summary, our contributions are as follows: 2
3 We show that we need a richer form of constraints to precisely capture the typing problem for multi-parameter type classes with existential types and type annotations. Thus, we can precisely explain why we lose principality and completeness of inference and which type inference methods are necessary to improve this unpleasant situation (Sections 2 and 5). We introduce a solving procedure for implication constraints. Thus, we obtain sound type inference for MPTC programs (Section 6). We investigate under which conditions inference is complete and inferred types are principal (Section 7): In case type class constraints are fixed (this can be enforced by type annotations) we obtain principal types (Section 7.1). In case all parameters of type class constraints in data type definitions are universally quantified each inferred type is principal. Though, inference is still incomplete in the sense that we may fail while a valid type exists (Section 7.2). For the general case, we can give a refined inference procedure which enumerates all possible types (Section 8). We continue in Section 2 where we give an overview of the main problems we face and how we intend to solve them. In Section 3 we introduce some preliminary definitions and spell out some basic assumptions. In Section 4 we briefly introduce the MPTC system. We conclude in Section 9. 2 Overview The standard route towards type inference is to generate an appropriate constraint out of the program text. The solution of these constraints yields a solution to type inference. E.g., in case of Hindley/Milner, we generate type equation constraints which can be solved by a unification procedure [Rob65]. In case of extensions of Hindley/Milner with subtypes [Pot98] or records [Rém93] we need to solve additional primitive constraints. For many extensions of Hindley/Milner, we can generalize this process by abstracting over the particular constraint domain [OSW99,Sul00]. The common type inference path is that we need to solve sets of primitive constraints such as type equations, subtype and record constraints. For MPTC type inference we need a richer form of constraints to capture precisely the typing problem. The significant difference compared to Hindley/Milner is that we additionally need Boolean implication ( ) and universal quantification (we will see shortly why). We refer to these constraints as implication constraints. The idea of using such constraints for type inference dates back to Zenger s index types [Zen99]. Our formulation follows Simonet and Pottier [SP05] who recently formalized implication constraint generation for an extension of Hindley/Milner. In case of the program from the introduction class Foo a b where foo::a->b->int instance Foo a Int where foo = 1 -- (F1) instance Foo a Bool where foo = 2 -- (F2) data Bar = forall b. Mk b f x z = (case z of (Mk y) -> foo y x, x == length []) 3
4 the following (simplified) implication constraint arises out of the program text of f. t f = t x Bar t 1, t 1 = (t 2, Bool), t x = Int, t y.(true Foo t y t x, t 2 = Int) Note that only the trivial T rue (assumption) constraint arises out of the pattern (Mk y). Hence, we could further simplify (True Foo t y t x, t x = Int) to Foo t y t x, t x = Int. The universal quantifier t y ensures that no existential variables escapes. We find that t f = Int Bar (Int, Bool) is a valid solution, hence, f::int->bar->(int,bool) is a correct type as we have already observed earlier. In existing implementations such as GHC, a traditional algorithm W style inference system is employed where we only generate sets of primitive constraints. Hence, language features such as type classes with type annotations and existential types demand that we perform additional tests while traversing the abstract syntax tree (AST). E.g., type inference for type classes with existential types demands that we additionally check that none of the existential variables escapes. In GHC, we traverse the AST from left-to-right. Hence, in function f we first consider the sub-expression case z of (Mk y) -> foo y x without considering x == length []. Then, foo y x gives rise to the constraint Foo t y t x. We cannot let Foo t y t x float out because t y is universally quantified (because y is a existential variable). However, we also cannot satisfy this constraint (the type inferencer would not to guess that t x = Int). Hence, type inference in GHC fails. The situation is similar for Hugs, though, Hugs seems to favor a right-to-left traversal of the AST. With implication constraints we can directly express additional inference tests. Hence, we can take advantage of constraints from the surrounding context while solving. Thus, we obtain an improved inference algorithm. But, we still face the incompleteness problem. E.g., f3 x z = case z of (Mk y) -> foo y x gives rise to t f3 = t x Bar t 1, t y.(true Foo t y t x, t 1 = Int) By guessing we find that t f3 = Int Bar Int and t f3 = Bool Bar Int are two incomparable solutions and there is no more general solution. The trouble is that the set of constraints specifiable by users is from a less expressive constraint domain than those (implication) constraints necessary to represent the typing problem. Hence, we may need to guess a solution. A trivial way out of this dilemma seems to enrich the user constraint domain, e.g., we could take the implication constraint itself as a solution. However, types then become unreadable and we still need to verify that implication constraints are satisfiable which seems as hard a problem as solving them. We employ an extension of algorithm W where we generate implication constraints out of the program text. Details are in Section 5. In Section 6 we show how to solve such constraints. To attack the completeness of inference problem we propose the following three approaches. In our first approach, we identify sufficient conditions under which solving of implication constraints always yields a most general solution or no solution 4
5 exists. We demand that the type of each type class method which appears within a type annotation or case expression must fixed (e.g. by a type annotation). Thus, we rule out function f3. Details are in Section 7.1. The above conditions are quite severe. E.g., we also rule out function f, though, the surrounding context implicitly constrains the type class method. In our second approach, we do not impose any conditions and the maybe surprising result is that if inference succeeds, then the inferred type is principal. For this to hold, we must require that all parameters of type class constraints in data type definitions are universally quantified. Unfortunately, we may miss some valid types. Details are in Section 7.2. In our final approach, we solve implication constraints locally by enumerating all finitely many solutions. E.g., in case of function f we first solve the subproblem t y.(true Foo t y t x, t 2 = Int) which has the two solutions t 2 = Int, t x = Int and t 2 = Int, t x = Bool. We then test which of these solutions is consistent with the solutions for the other sub-problems. Here, we find that only t 2 = Int, t x = Int is consistent with t f = t x Bar t 1, t 1 = (t 2, Bool), t x = Int. Hence, t f = Int Bar (Int, Bool) is the final answer. Thus, we obtain complete inference, however, we lose principality. E.g., in case of function f3 we infer that Int->Bar->Int and Bool->Bar->Int are the two possible types which can be given to f3. But there is no more general type. Details are in Section 8. 3 Preliminaries For convenience, we write ō as a short-hand for a sequence of objects o 1,..., o n (e.g. expressions, types etc). As it is common, we write Γ to denote an environment consisting of a sequence of type assignments x 1 : σ 1,..., x n : σ n. Types σ will be defined later. We commonly treat Γ as a set. We write to denote set subtraction. We write fv(o) to denote the free variables in some object o. We generally assume that the reader is familiar with the concepts of substitutions, unifiers, most general unifiers (m.g.u.) etc [LMM87] and first-order logic [Sho67]. We write [t/a] to denote the simultaneous substitution of variables a i by types t i for i = 1,.., n. We use common notation for Boolean conjunction ( ), implication ( ) and universal ( ) and existential quantifiers ( ). Often, we abbreviate by, and use set notation for conjunction of formulae. We sometimes use V.Fml as a short-hand for fv(fml) V.Fml where Fml is some first-order formula and V a set of variables, that is existential quantification of all variables in Fml apart from V. We write = to denote the model-theoretic entailment relation. When writing logical statements we often leave (outermost) quantifiers implicit. E.g., let Fml 1 and Fml 2 be two formulae where Fml 1 is closed (contains no free variables). Then, Fml 1 = Fml 2 is a short-hand for Fml 1 = fv(fml 2 ).Fml 2 stating that in any (first-order) model for Fml 1 formula fv(fml 2 ).Fml 2 is satisfied. 4 Multi-Parameter Type Classes We first describe the syntax of MPTC programs. Then, we make use of our earlier work [SS02] to explain the meaning of type classes in terms of Constraint 5
6 Handling Rules (CHRs) [Frü95]. Finally, we state some basic conditions which ensure that CHRs resulting from MPTC programs are well-behaved. Expressions e ::= K x λx.e e e let g = e in e let g :: C t case e of in e g = e [p i e i ] i I Patterns p ::= x K p...p Types t ::= a t t T t Type Classes tc ::= TC t Constraints C ::= tc C C Type Schemes σ ::= t ā.c t Data Decls ddec ::= data T a 1...a m = forall b 1,..., b n.c K t 1...t l Type Class Decls tcdec ::= class TC ā wherem :: C t instance C TC t CHRs chr ::= rule TC t C We assume that K refers to constructors of user-defined data types. Patterns must be linear, i.e., each variable occurs at most once. Type annotations are closed, i.e. in f::c=>t we quantify over all variables in fv(c, t). The extension with lexically scoped annotations is straightforward but omitted for simplicity. We assume that let-defined functions carrying an annotation may be recursive, though, we ignore un-annotated recursive functions for simplicity. We assume that user-defined types T t are introduced via data type declarations of the form data T a1... am = forall b1,...,bn. C => K t1... tl We assume that these declarations are preprocessed and the types of constructors K : ā, b.c t 1... t l T ā are recorded in the initial environment Γ init. We assume that ā b =. Note that ā and b can be empty. Similarly, for each class declaration class TC ā where m :: C t we find m : fv(c, t, ā).(tc ā, C) t Γ init. For brevity, we ignore super-classes. Following [SS02], we translate each declaration instance C TC t into a CHR rule TC t C. We assume that the set P contains all CHRs resulting from instance declarations. Commonly, we refer to P as the program theory. Logically, each CHR rule TC t C can be interpreted as the first-order formula fv( t).t C t fv(c) fv( t).c. CHRs also have a simple operational reading which we explain shortly. In the absence of existential types and type annotations, type inference for type classes can be straightforwardly reduced to CHR solving [SS02]. In their presence, we need an extension of the CHR solving mechanism which is discussed in Section 6. We now briefly explain the operational semantics of CHRs (see e.g. [SS02] for more details). CHRs specify a rewrite relation among constraints. We can apply rule TC t C 3 to a set of constraints C if we find a matching copy TC s C such that φ( t) = s for some substitution φ. Then, we replace TC s by the right-hand side under the matching substitution φ(c) More formally, we write C C TC s φ(c) to denote this derivation step. Later we will consider derivations that have a mix of type equations C e and type class 3 We assume that variables in CHRs are renamed before rule application. 6
7 constraints C t. In this case we assume the first step in the CHR derivation maps C e, C t x = t, θ(c t ) where θ = { x/ t} is the mgu of C e. That is we apply the mgu to all type class constraints and replace the equations by a canonical form mgu. For a given program theory P and initial constraint (store) C, we write C P C to denote the exhaustive application of CHRs P resulting in the final constraint C. Of course, CHR derivations may be non-terminating and non-confluent, i.e., a different order of rule applications yields a different result. Termination and confluence of CHRs are crucial properties such that type inference is well-behaved. The following conditions are commonly imposed on multi-parameter type classes [GHC] such that resulting CHRs are well-behaved. Definition 1 (Haskell Multi-Parameter Type Class Restrictions). The left-hand side (a.k.a. context) C of an instance declaration can mention only type variables, not type constructors. In an instance declaration instance C U t 1... t n, at least one of the types t i must not be a type variable and fv(c) fv(t 1,..., t n ). The instance declarations must not overlap. That is, for any two instances declarations instance C => TC t 1... t n and instance C => TC t 1... t n there is no substitution φ such that φ(t 1 ) = φ(t 1 ),...,φ(t n) = φ(t n ). Type classes appearing in programs are unambiguous. A formal definition can be found in the following section. The first three conditions ensure that the translation from instance declarations to CHRs yield a program theory for which CHR solving is complete [SS02]. The last condition ensures that all type class parameters are uniquely determined. This is a natural restriction and ensures that the meaning of programs is deterministic [Jon93]. Among some other conditions, unambiguity ensures that we do not need to guess types in case of type inference. The set of well-typed MPTC programs is formally defined in the next section. 5 Type Inference via Implication Constraints We show how type inference can be reduced to solving of implication constraints. Constraints C ::= t = t TC t C C ImpConstraints F ::= C b.(c ā.f) F F Commonly, we use symbols C and D to refer to constraints. To obtain a type inference result, we need to find a solution of a implication constraint in terms of a set of primitive constraints. Definition 2 (Solutions). Let P be a program theory, F an implication constraint and C a constraint. We say C is a solution of F w.r.t. P iff P = C F. In such a situation, we write C = solve(f P). We say C is a principal solution iff (1) C is a solution, and (2) for any other solution C we have that P = C fv(f).c. 7
8 (x : ā.c t) Γ (Var) Γ, x W (C t) (LetA) ā = fv(c 1, t 1) Γ {g : ā.c 1 t 1}, e 1 W (F 1 t 1) Γ {g : ā.c 1 t 1}, e 2 W (F 2 t 2) F F 2 ā.(c 1 fv(γ,t1 ).F1 t1 = t 1) Γ,let g :: C1 t1 g = e 1 in e 2 W (F t 2) (App) V, Γ, e 1 W (F 1 t 1) C 1 = solve(f 1 P) ā = fv(c 1,t 1) fv(γ) (Let) V, Γ {g : ā.c 1 t 1}, e 2 W (F 2 t 2) V, Γ,let g = e 1 in e 2 W (F 2 t 2) Γ, e 1 W (F 1 t 1) tenv, e 2 W (F 2 t 2) t fresh F F 1 F 2 t 1 = t 2 t Γ, e 1 e 2 W (F t) (Case) (Abs) a fresh Γ {x : a}, e W (F t) Γ, λx.e W (F a t) Γ, p i e i W (F i t i) for i I Γ, e W (F e t e) t 1, t 2 fresh F F e t 1 = t e t 2 V i I (Fi t1 = t i) Γ,case e of [p i e i] i I W (F t 2) (Pat) p b.(d Γ p t 1) Γ Γ p, e W (F e t e) t fresh F b.(d fv(γ, b,te).fe) t = t1 te Γ, p e W (F t) (Pat-K) (Pat-Var) t fresh x (True {x : t} t) K : ā, b.d t 1... t l T ā b ā = p k b k.(d k Γ pk t pk ) φ m.g.u. of t pk = t k for k = 1,..., l dom(φ) b = K p 1...p l b 1,..., b l, b.(φ(d 1)...φ(D l) φ(d) φ(γ p1 )... φ(γ pl ) T φ(ā)) Fig.1. Type Inference via Implication Constraints Note that P = C F states that in any model M which satisfies the logical interpretation of CHRs P and constraint C we find that implication constraint F is satisfied too. Thus equipped, we introduce a algorithm W style inference system where we generate implication constraints out of the program text and solve them before building type schemes at let statements. How to solve such constraints will be discussed in Section 6. The algorithm is formulated in terms of a deduction system where we make use of judgments of the form Γ, e W (F t) where environment Γ and expression 8
9 e are input values and implication constraint F and type t are output values. For patterns we introduce an auxiliary judgment of the form p b.(d Γ t) to compute the set of existential variables b, constraint D, environment Γ and type t arising out of pattern p. Details are in Figure 1. Note that the statement t fresh is meant to introduce a fresh type variable t. We briefly review the individual rules. Note that we write to denote syntactic equality to avoid confusion with equality among types. In rules (Var) and (Pat-K) we assume that the bound variables ā and b are fresh. In rule (Pat) we make use of the implication constraint b.(d fv(γ, b,te).f e) which states that under the temporary assumptions D arising out of the pattern p we can satisfy the implication constraint F e arising out of e. The quantifier ensures that no existential variables b escape. Note that fv(γ, b,te).f e is a short-hand for ā.f e where ā = fv(f e ) fv(γ, b, t e ). That is, we existentially quantify over all variables which are strictly local in F e. In rule (LetA) we again make use of implication constraints to represent the subsumption problem among two type schemes. In rule (Let) we need to solve implication constraints before we can build the type scheme. Based on our inference system, we can define the set of well-typed MPTC programs. Definition 3 (Well-Typed MPTC Program). Let P be the program theory resulting from translating instances to CHRs. Let e be an expression and Γ be an environment. We say that e is well-typed under Γ iff we find constraint C, type t such that P = (C t = t ) F where Γ, e W (F t ). In such a situation, we write C, Γ e : t. We do not verify type soundness here which we take for granted. It is straightforward to show that principal solutions imply principal types. Let P be a program theory, Γ an environment and e an expression. We say (C, t) is a principal type iff (1) C, Γ e : t, and (2) if C, Γ e : t then P = C fv(γ).(c t = t ). Theorem 1 (Principal Types). Let P be a program theory. Let Γ be an environment and e be an expression such that all implication constraints generated from (Γ, e) have a principal solution. Then, (Γ, e) has a principal type. The above result is important and justifies that we can focus on solving of implication constraints for the rest of the paper. For convenience, all solving procedures in the following sections operate on normalized constraints. We also define type class unambiguity in terms of normalized constraints at the end of this section. Normalization of constraints proceeds as follows. In a first step, we transform implication constraints based on the following first-order equivalences: (i) (F 1 Qa.F 2 ) Qa.(F 1 F 2 ) where a fv(f 1 ) and (ii) (Qa.F 1 ) (Qb.F 2 ) Qa, b.(f 1 F 2 ) where a fv(f 2 ), b fv(f 1 ) and Q {, } and (iii) C 1 (C 2 C 3 ) (C 1 C 2 ) C 3. We exhaustively apply the above identities from left to right. Lemma 1 (Normalization). Each implication constraint resulting from Figure 1 can be equivalently represented by C 0 Q.((D 1 C 1 )... (D n C n )) (1) where Q is a mixed prefix of the form b 0. a 1. b 1... a n. b n. 9
10 Note that no explicit quantifier scopes over C 0 (variables in C 0 are implicitly existentially quantified). We apply Skolemization [Mil92] to formula (1) and remove universal quantifiers. That is, we transform b. ā.f into b.[sk a ( b)/ā]f where Sk ai s are some fresh Skolem constructors. We apply this step repeatedly until we reach the form C 0 b.((d 1 C 1)... (D n C n)) (2). Note that Skolemization is (in general) not a satisfiability preserving transformation. However, based on our specific assumptions (only multi-parameter type class constraints to the left of implication, only single-headed simplification rules where there are no type equations on the rhs), we are able to guarantee that any solution to the transformed constraint yields a solution to the original constraint. We formally define type class unambiguity. We say that C 0 b.((d 1 C 1 )... (D n C n )) is unambiguous iff fv(d i, C i, C 0 ) fv(c 0 ) for i = 1,..., n. We assume a semantic oriented definition of the set of free variables in a constraint where fv(c) = {a = a.c C}. Thus, we can argue that existentially bound variables b are uniquely determined by variables in fv(c 0 ). Hence, we can safely drop the existential quantifier b. This is important and avoids us from guessing types. Definition 4 (Unambiguous MPTC Program). We say a well-typed MPTC program is unambiguous iff all normalized and Skolemized implication constraints arising in inference derivations are unambiguous and for each type scheme ā.c t appearing we have that fv(c, t) fv(ā). We can check for unambiguity as follows. It suffices to consider a single normalized and Skolemized constraint F C 0 (D C). We simply build C 0 s m.g.u. φ and apply it to D and C and check whether any free variables other than fv(φ(c 0 )) remain. If this is the case, F is unambiguous. Note that because we apply the m.g.u. it is sufficient to calculate the set of syntactically free type variables. Based on a similar method we can check that a type scheme is unambiguous. 6 Solving of Implication Constraints We introduce a general-purpose procedure to solve implication constraints arising out of MPTC programs. Thus, we obtain sound type inference. Before we consider the solving problem we investigate the checking problem. We consider a (local) sub-problem of the form D C. The following methods can be easily extended to deal with conjunctions of sub-problems. Lemma 2 (Checking). Let P be a MPTC program theory. Let D C be a implication constraint. Then, S is a solution if (1) S, D P D and (2) S, D, C P C such that (3) = D C. Note that D C iff D D, C. Hence, S is a solution if S, D S, D, C holds in the program theory P. Following our earlier work [SS02], we can check for the last statement by executing (1) and (2). The test (3) verifies that the final stores are logically equivalent. Effectively, we check that m.g.u. in both stores are equivalent and type class constraints are syntactically equivalent (after applying the m.g.u.). Note that MPTC instances never introduce any fresh 10
11 variables (see second condition of Definition 1). Hence, fv(d ) fv(s, D) and fv(c ) fv(s, D, C). In the case the constraints are unambiguous, we have that fv(s, D) = fv(s, D, C). Then, the above check is even complete. Of course, for type inference we need more than checking. Though, checking for solutions provides us with some vital clues how to solve implication constraints. Consider D C and assume we check whether True is a solution. In case the check fails, the best guess we can make is to add the difference between final stores being careful not to let universal variables (represented by Skolem constructors) escape. Then, we check again and so on. Based on this observation we suggest the following solving procedure. General solving method: Consider the normalized and Skolemized implication constraint F C 0, (D C), F. We execute C 0, D P D and C 0, D, C P C for some D and C. If False C we immediately fail. If C D yields the empty set (i.e. final stores are logically equivalent) we consider the implication as solved and continue with C 0, F. We immediately stop in case F is empty. Otherwise, we set S to be the subset of all constraints in C D which do not refer to a Skolem constructor. In case S is non-empty, we continue with C 0, S, (D C ), F. In case S is empty, we pick some (D 1 C 1 ) F and continue with C 0, (D 1 C 1 ), F (D 1 C 1 ), (D C). Otherwise, we fail. We illustrate our solving method by an example. Consider class Foo a b where foo::b->a->int instance Foo Int b -- (F) class Bar a b where bar :: b->a->a data Erk a = forall b. Bar a b => K1 (a,b) forall b. K2 (a,b) g (K1 (a,b)) = bar b a g (K2 (a,b)) = foo b a Here is the (slightly simplified) implication constraint arising out of g s program text. Note that t refers to the type of g. t = Erk a t 3 t 3 = t 1 t 3 = t 2 b.(bar a b Bar a b, t 1 = a) b.(true Foo a b, t 2 = Int) We find that t = Erk a t 3, t 3 = t 1, t 2 = t 1, t 1 = a, t 2 = Int is a solution. Indeed, also GHC infers that g has the type Erk Int->Int. In our solving method we Skolemize constraints which leads to t = Erk a t 3 t 3 = t 1 t 3 = t 2 (C 0 ) (Bar a Sk 1 Bar a Sk 1, t 1 = a) (1) (True Foo a Sk 2, t 2 = Int) (2) Assume we starting solving sub-problem (1). We find that S 1 t 1 = a after taking the difference between final stores. Hence, we continue with C 0, S 1 and we can then verify that (1) is solved by C 0, S 1. Consider sub-problem (2). We find that S 2 t 2 = Int. Finally, we can verify that C 0, S 1, S 2 solves sub-problem (2) and we obtain that g has type Erk Int->Int. Note that if we start solving with (2) we encounter S 1 t 2 = Int. We cannot solve (2) yet. Hence, we consider (1) which leads to S 2 t 1 = a. Then, we can 11
12 verify that C 0, S 1, S 2 solves (1) and (2). Obviously, we obtain the same result. Note that Erk Int->Int is the principal type here. We conclude this section by stating the following results. Lemma 3 (Solving). Let P be a MPTC program theory and F a normalized and Skolemized implication constraint. Every constraint S obtained by the general solving method is a valid solution of F w.r.t. P. We can apply the general solving procedure to check whether a MPTC program is well-typed. Theorem 2 (Soundness of MPTC Type Inference). We achieve sound type inference for MPTC programs. Note that our inference method succeeds for function f from the introduction. However, we still fail for function f3. Hence, our inference method is incomplete. Next, we discuss how to achieve complete type inference where the inferred type is principal. 7 Principal Types for MPTC We identify two conditions under which we obtain principal types. The first condition demands that the type class constraints arising on the right-hand side of must be fixed. This can be enforced by type annotations. The second condition demands that all constraints on the left-hand side of are universal. That is, all parameters of type class constraints in data type definitions are universally quantified. For both conditions we must additionally demand that the instances satisfy the Haskell multi-parameter type class restrictions (Definition 1). We refer to the set P of CHRs resulting from such instances as a MPTC program theory. 7.1 Fixed Condition In our first result we characterize under which conditions the solutions computed by the general solving method from the previous sections are principal. Lemma 4 (Local Principal Solutions). Let P be a MPTC program theory and F C 0 (D C) be a normalized, Skolemized and unambiguous MPTC implication constraint such that D P D and D, C P C for some D and C. Let S be the set difference between C and D, i.e. S = C D. Then, C 0, S is a principal solution of F if (1) S does not contain False and (2) each type-class constraint in S does not refer to a Skolem constructor and (3) F has a solution. A proof can be found in Appendix A. Note that we can decide whether the conditions of Lemma 4 are satisfied. Conditions (1) and (2) can be easily checked. To verify condition (3) we can simply test whether C 0, S is a solution based on the above method (note that the lemma guarantees then that C 0, S must be principal). Checking for unambiguity is discussed at the end of Section 5. Our next result (which holds for arbitrary program theories and implication constraints) shows how to combine locally computed principal solutions. 12
13 Lemma 5 (Combining Principal Solutions). Let P be a program theory. Let F 1 and F 2 be two implication constraints and S 1 and S 2 be two constraints such that S 1 is a principal solution of F 1 and S 2 is a principal solution of F 2. Then, S 1 S 2 is a principal solution of F 1 F 2. Proof: Note that S 1 S 2 is a solution of F 1 F 2. Assume S F 1 F 2. Hence, S F 1 and S F 2. S 1 and S 2 are principal. Hence, S S 1 and S S 2 which shows that S S 1 S 2. Immediately, we can state the following result. Lemma 6 (Local Principal Types for MPTC). We can infer principal types for multi-parameter type classes satisfying the MPTC conditions if local principal solutions exist and programs are unambiguous. To guarantee that local principal solutions exist we require that the type of each type class method which appears within a type annotation or case expression must be explicitly annotated. In such a situation we say that type class methods are fixed. Fixed type class methods imply that the type parameters of type class constraints are fixed. Hence, we can guarantee that local principal solutions exists or no solutions exists at all. We summarize. Theorem 3 (Principal Types for Fixed MPTC). We can infer principal types for multi-parameter type classes satisfying the Haskell multi-parameter type class conditions if type class methods are fixed. Note that the fixed conditions implies that programs are unambiguous. Instead of fixing the type of type class methods, we conjecture that we can equivalently demand that parameters of type class constraints on the right-hand side of implication constraints are universally quantified (which implies that these constraints arise from method applications to existential variables). For the specific case of single-parameter type classes, the single parameter of a type classes is either universally quantified or unbound. Hence, there is no need to impose the fixed conditions. Hence, we can easily verify the following result which has been proven before by Läufer [Läu96]. Corollary 1. We can infer principal types for single-parameter type classes satisfying the Haskell multi-parameter type class conditions. Note that in order to sufficiently annotate programs, we may need pattern annotations and lexically scoped annotations. E.g., in case of function f the following annotations are sufficient. f x z = (case z of (Mk (y::b)) -> (foo::b->int->int) y x, x == length []) However, our current syntax does not support such forms of annotations. The extension is fairly straightforward and is discussed elsewhere [SW05]. 7.2 Universal Condition Instead of the fixed condition we demand that all type class parameters in data type definitions are universally quantified. In such a case constraints on the 13
14 left-hand side of are fully Skolemized. In such a situation, we say that the universal condition is satisfied. Note that the example from the introduction satisfies this condition (trivially) whereas in the example from Section 6 definition Erk a contains the type class constraint Bar a b whose parameter a is not universally quantified. If left-hand side constraints are fully Skolemized and the Haskell multi-parameter type class restrictions hold we can guarantee that these constraints will not introduce any fresh variables while solving. Hence, all (partial) solutions will either lead to a principal solution or we reach failure. Theorem 4 (Principal Types for Universal MPTC). For each program which satisfies the Haskell multi-parameter type class restrictions and all parameters of type class constraints in data type definitions are universally quantified, if inference succeeds, then the inferred type is principal. Note that our inference method fails for function f3 from the introduction which satisfies the universal condition. Though, as we have observed function f3 has no principal type. We conjecture that failure of our solving method implies that the program has no principal type. The condition that all parameters of type class constraints in data type definitions are universally quantified is crucial to establish the above result. Consider class Foo a class Bar a b where bar :: a->b instance Foo a => Bar a [a] data Erk a = Foo a => Mk a f (Mk x) = bar x In the data type definition for Erk a we find the type class constraint Foo a where a is not universally quantified. Our inference method applied to the normalized and Skolemized implication constraint t f = Erk a b, (Foo a Bar a b) yields the solution Bar a b, t f = Erk a b. However, the type Bar a b => Erk a->b is not principal. E.g., we can give f the incomparable type Erk a->[a]. The above suggests that it is not obvious how to relax the fixed and universal condition while maintaining complete inference with principal types. In general, the only way to obtain complete inference seems to enumerate all possible solutions. This is what we discuss in the next section. 8 Complete and Semi-Decidable Type Inference The basic idea of our complete inference method is to unify constraints to find further possible solutions. Consider the implication constraint t f = Erk a b, (Foo a Bar a b) from the previous section. We execute (the calculations here are trivial, no CHR applies) t f = Erk a b, Foo a t f = Erk a b, Foo a 14
15 and t f = Erk a b, Foo a, Bar a b t f = Erk a b, Foo a, Bar a b We unify Bar a b against the head of the instance instance Foo a => Bar a [a] which yields b = [a]. Thus, we find the additional solution t f = Erk a [a]. The following example shows that we may also need to unify constraints which arise from the left-hand side of. Consider the code class Foo a b where foo::a->b class Foo2 a b instance Foo b a => Foo2 b [a] data Erk a = forall b. Foo2 b a => Mk b g (Mk x) = foo x In inferring the type of g we obtain the (simplified) constraints or Skolemized as t = Erk a c b.(foo2 b a Foo b c) t = Erk a c (Foo2 Sk a Foo Sk c) While there is no instance of Foo to match Foo Sk c, there is a unique principal solution t = Erk [c] c, given by assuming that a = [c]. This arises from unifying the constraint Foo2 Sk a on the left hand side with the instance head. In general, the complete solving method is as follows. We will manipulate a set of implication constraints F representing the possible solutions of the original implication constraint F. Initially F = {F }. Choose an implication constraint F F. Apply the incomplete method of the previous section. If it succeeds then we add the solution C 0 to F built by the process. Suppose F is of the form C 0, (D C), F. where such that C D is not empty where C 0, D P D and C 0, D, C P C. If it contains a type equation, then it must include Skolem constructors, which would require them to escape so we can conclude that F has no solutions, and simply remove it from F. Otherwise we choose a type class constraint TC s in C D or D C. For each (renamed apart) instance declaration rule TC t C, where the mgu of s = t exists we create a new implication constraint C 0, ( fv( s). s = t), (D C ), F. Note that by writing ( fv( s). s = t) we denote the projection of type equations s = t onto variables fv( s). Thus, we avoid to introduce spurious type equations containing Skolem constructors. E.g., when unifying F oo2 Sk a against the instance head we generate the spurious constraint b = Sk which will be projected away. Additionally if TC s appears in C then for each unifying type class constraint TC ū appearing in the D, where the mgu of ū = s exists we create new implication constraints C 0, ( fv( s). s = ū), (D C ), F. We add each of the new implication constraints constructed above to F and continue. Examining f3 the Skolemized simplified constraint F is t = t x Bar Int, (True Foo Sk t x ) 15
16 and F = {F } At this point the incomplete method fails. The complete method selects the only type class constraint and using the two unifying instances for Foo Sk t x builds two new implication constraints {F 1, F 2 } defined by F 1 t = t x Bar Int, t x = Int, (True Foo Sk t x ) F 2 t = t x Bar Int, t x = Bool, (True Foo Sk t x ) These two implication constraints are solvable (by the incomplete method) giving constraints t = t x Bar Int, t x = Int t = t x Bar Int, t x = Bool which are the two possible solutions. Lemma 7. Let E be a satisfiable constraint not involving Skolem constructors arising out of the procedure above. Then E = solve(f, P), that is, it is a solution of F. Proof: Each of the new implication constraints is a consequence of the original constraint F, hence any solutions to them are solutions to F. Theorem 5. Let P be a program satisfying the MPTC conditions, and let F be a normalized, Skolemized and unambiguous MPTC implication constraint. Let E = solve(f P). Let {E 1,...,E n,...} be the set of constraints (solutions not implication constraints) arising out of the complete procedure above. Then i.e E i. A proof is given in Appendix B. The complete algorithm as defined above is clearly non-terminating, but with a fair breadth first search procedure we create a semi-decision procedure that eventually discovers each individual solution. We could clearly make the algorithm more deterministic, but there is an underlying problem of non-termination. Consider the declarations class Foo a b instance F a b => Foo [a] b Assume we attempt to solve F True Foo c Sk. We unify Foo c Sk with the instance head which leads to c = [d], (True Foo c Sk). In the next step we have that c = [d], Foo c Sk c = [d], Foo d Sk and a variant of the same unmatched constraint F oo d Sk arises. It interesting further work to see when can safely detect such cycles. 9 Conclusion We have pointed out subtle problems when performing type inference for multiparameter type classes with existential types and type annotations. We could propose a number of novel inference methods under which we retain principality and completeness of type inference. To the best of our knowledge, we are the first to identify the inference problem and to suggest several potential solutions. An interesting question is what will happen in case we include further features such as functional dependencies [Jon00]. We plan to pursue this topic in the future. 16
17 References [DM82] L. Damas and R. Milner. Principal type-schemes for functional programs. In Proc. of POPL 82, pages ACM Press, January [Fax03] K. F. Faxén. Haskell and principal types. In Proc. of Haskell Workshop 03, pages ACM Press, [Frü95] T. Frühwirth. Constraint handling rules. In Constraint Programming: Basics and Trends, LNCS. Springer-Verlag, [GHC] Glasgow haskell compiler home page. [Has] Haskell 98 language report. haskell98-revised/haskell98-report-html/. [HUG] Hugs home page. haskell.cs.yale.edu/hugs/. [JJM97] S. Peyton Jones, M. P. Jones, and E. Meijer. Type classes: an exploration of the design space. In Haskell Workshop, June [JN00] M. P. Jones and J. Nordlander, [Jon92] M. P. Jones. Qualified Types: Theory and Practice. D.phil. thesis, Oxford University, September [Jon93] M. P. Jones. Coherence for qualified types. Research Report YALEU/DCS/RR-989, Yale University, Department of Computer Science, September [Jon95] M. P. Jones. Simplifying and improving qualified types. In FPCA 95: Conference on Functional Programming Languages and Computer Architecture. ACM Press, [Jon00] M. P. Jones. Type classes with functional dependencies. In Proc. of ESOP 00, volume 1782 of LNCS. Springer-Verlag, [Läu96] K. Läufer. Type classes with existential types. Journal of Functional Programming, 6(3): , [LMM87] J. Lassez, M. Maher, and K. Marriott. Unification revisited. In Foundations of Deductive Databases and Logic Programming. Morgan Kauffman, [LO94] K. Läufer and M. Odersky. Polymorphic type inference and abstract data types. ACM Trans. Program. Lang. Syst., 16(5): , [Mil78] R. Milner. A theory of type polymorphism in programming. Journal of Computer and System Sciences, 17: , Dec [Mil92] Dale Miller. Unification under a mixed prefix. J. Symb. Comput., 14(4): , [OL96] M. Odersky and K. Läufer. Putting type annotations to work. In Proc. of POPL 96, pages ACM Press, [OSW99] M. Odersky, M. Sulzmann, and M Wehr. Type inference with constrained [Pot98] types. Theory and Practice of Object Systems, 5(1):35 55, F. Pottier. A framework for type inference with subtyping. In Proc. of ICFP 98, pages ACM Press, [Rém93] D. Rémy. Type inference for records in a natural extension of ML. In Carl A. Gunter and John C. Mitchell, editors, Theoretical Aspects Of Object-Oriented Programming. Types, Semantics and Language Design. MIT Press, [Rob65] J. A. Robinson. A machine-oriented logic based on the resolution principle. Journal of the Association for Computing Machinery, 12:23 41, [Sho67] J.R. Shoenfield. Mathematical Logic. Addison-Wesley, [SP05] [SS02] [Sul00] V. Simonet and F. Pottier. Constraint-based type inference for guarded algebraic data types. Research Report 5462, INRIA, January P. J. Stuckey and M. Sulzmann. A theory of overloading. In Proc. of ICFP 02, pages ACM Press, M. Sulzmann. A General Framework for Hindley/Milner Type Systems with Constraints. PhD thesis, Yale University, Department of Computer Science, May
18 [SW05] M. Sulzmann and J. Wazny. Lexically scoped type annotations. sulzmann, [Zen99] C. Zenger. Indizierte Typen. PhD thesis, Universität Karlsruhe, A Proof of Lemma 4 In preparation, we state the following result which can be proven by induction over the CHR derivations. Lemma 8. Let P be a MPTC program theory. Let C, D 2 P C 1 and C, D 1, D 2 P C 2 such that fv(d 1, D 2 ) fv(c) and = C 1 C 2. Then, C P C 1 and C, D 1 D 2 P C 2 such that = C 1 C 2. We also restate (a specific instance of) the Canonical Normal Form Lemma from [SS02]. Lemma 9. Let P be a MPTC program theory. We have that P = D C iff D P D and D, C P C where = D C. We verify Lemma 4: Let P be a MPTC program theory and F C 0 (D C) be a normalized, Skolemized and unambiguous MPTC implication constraint such that D P D and D, C P C for some D and C. Let S be the set difference between C and D, i.e. S = C D. Then, C 0, S is a principal solution of F if (1) S does not contain False and (2) each type-class constraint in S does not refer to a Skolem constructor and (3) F has a solution. Proof: Condition (1) is obvious. Condition (2) prevents existential variables (which are Skolemized in the normalized constraint) from escaping. Condition (3) is interesting. If F has a solved form, then adding the difference among final stores yields a principal solved form. The proof goes as follows. We first show that if S is a solved form then S S, C 0, hence, S, C 0 is principal. W.l.o.g., we assume that fv(s ) = fv(c 0 ). Note that Skolemization is a satisfiability preserving transformation. Hence, if S is a solved form then P = S (C 0, (D C)). Note that constraints are unambiguous, hence, we could drop all existential quantifiers. We have that P = S (C 0, (D C)) iff P = S C 0 and P = (S, D) C which yields P = S, D S, D, C (4). Soundness of CHR solving and range-restriction allows us to conclude that from D P D and D, C P C that = D D and = D, C C (5). From (4) and (5) we conclude that P = S, D S, D, C. From Lemma 9 we conclude that S, D P C 1 and S, D, C P C 2 where = C 1 C 2 (recall that unambiguity implies that fv(d, C, C 0 ) fv(c 0 ) and by assumption fv(s ) = fv(c 0 ), hence, w.l.o.g. we assume that fv(d, C) fv(s ) which could be enforced by normalizing constraints by building the m.g.u.). From Lemma 8 we obtain that S P C 1 and S, C D P C 2 where = C 1 C 2. Lemma 9 finally yields that P = S C D. Hence, we have verified that C 0, C D is principal. We show that C 0, C D is a solved form, i.e. P = C 0, C D C 0, (D C). From Lemma 9 we conclude that this holds iff C 0, C D, D P C 1 and C 0, C D, D, C P C 2 where = C 1 C 2. We can verify this statements by induction over the CHR derivation. 18
19 We provide several examples to show that the Haskell restrictions are necessary. In terms of the CHR theory, these restrictions guarantee confluence and range-restriction (i.e. grounding the lhs of rule also grounds the rhs). First, we show that confluence is necessary. Example 1. We assume a constant constraint Foo, a unary constraint Erk and a binary constraint Bar and the non-confluent logic P = {Bar a b Foo Bar a b Erk b}. Consider the implication constraint b.true Bar a b which yields True Bar a Sk after normalization. We have Bar a Sk Erk Sk. Hence, our local principal solved form procedure suggests that T rue is a principal solved form. However, this is not the case. Note that we also have that Bar a Sk Foo which shows that Foo is a solved form. Next, we consider range-restrictedness. Example 2. We assume a unary constraint Bar and a binary constraint Foo and the non-range-restricted program logic P = {Bar a Foo a b}. Consider the implication constraint Foo a b Bar a. The logical reading of P is a.bar a b.foo a b. Hence, True is a solved form of Foo a b Bar a. Our procedure computes Foo a b Foo a b and Bar a Foo a b. We find that Foo a b is a solved form which is not principal. In our final example, we show that multi-headed rules break our result. Example 3. We assume three constant constraints Bar, Foo and Erk and the multi-headed logic P = {Foo, Bar Erk}. Consider Foo Bar. We have that Foo, Bar Erk. Indeed, Erk is a solved form but Bar is another incomparable solved form. Note that the same argument applies to multi-headed propagation rules. E.g., consider P p = {Foo, Bar = Erk}. B Proof of Theorem 5 Essentially the proof relies on the fact that in order for E to be a solution it must cause derivations from E, D P D and E, D, C P C where D C. These derivations arising for E will be explored by the complete algorithm, and hence it will construct a solution E using these derivations which is no more specific than E. The following lemma follows from the definition of derivation steps. Lemma 10. Let θ be the mgu of type equations E. Suppose that θ(tc s) φ(c) using the rule TC t C with matching φ where φ( t) = θ( s). Then E fv( s). s = t. Proof: Assume F is of the form C 0, (D C), F. Since E is a solution we have by Lemma 9 that for each Skolemized implication (D C) in F that E, D P D and E, D, C P C and D C. Let C 0, D P D and C 0, D, C P C By confluence of the CHR program there is a derivation E, D P D since E C 0. Similarly there must be a derivation E, C P C. In building one of the implication constraints F F the complete inference algorithm will mimic exactly all the derivation steps in these extra derivations 19
Principal Type Inference for GHC-Style Multi-Parameter Type Classes
Principal Type Inference for GHC-Style Multi-Parameter Type Classes Martin Sulzmann 1, Tom Schrijvers 2, and Peter J. Stuckey 3 1 School of Computing, National University of Singapore S16 Level 5, 3 Science
More informationKatholieke Universiteit Leuven Department of Computer Science
Type inference for GADTs via Herbrand constraint abduction Martin Sulzmann Tom Schrijvers Peter J. Stuckey Report CW 507, January 2008 Katholieke Universiteit Leuven Department of Computer Science Celestijnenlaan
More informationType Processing by Constraint Reasoning
, Martin Sulzmann, Jeremy Wazny 8th November 2006 Chameleon Chameleon is Haskell-style language treats type problems using constraints gives expressive error messages has a programmable type system Developers:
More informationA Framework for Extended Algebraic Data Types
A Framework for Extended Algebraic Data Types Martin Sulzmann 1, Jeremy Wazny 3 and Peter J. Stuckey 2,3 1 School of Computing, National University of Singapore S16 Level 5, 3 Science Drive 2, Singapore
More informationType Processing by Constraint Reasoning
Type Processing by Constraint Reasoning Peter J. Stuckey 1,2, Martin Sulzmann 3, and Jeremy Wazny 2 1 NICTA Victoria Laboratory 2 Department of Computer Science and Software Engineering University of Melbourne,
More informationSimple Unification-based Type Inference for GADTs
Simple Unification-based Type Inference for GADTs Stephanie Weirich University of Pennsylvania joint work with Dimitrios Vytiniotis, Simon Peyton Jones and Geoffrey Washburn Overview Goal: Add GADTs to
More informationFunctional dependencies versus type families and beyond
Functional dependencies versus type families and beyond Martin Sulzmann National University of Singapore Joint work with Tom Schrijvers Functional dependencies versus type families and beyond p.1 What
More informationWhere is ML type inference headed?
1 Constraint solving meets local shape inference September 2005 2 Types are good A type is a concise description of the behavior of a program fragment. Typechecking provides safety or security guarantees.
More informationConfluence for Non-Full Functional Dependencies
Chapter 2 Confluence for Non-Full Functional Dependencies Tom Schrijvers 1, Martin Sulzmann 2 Category: Research Paper Abstract: Previous work on type inference for functional dependencies demands that
More informationTracing Ambiguity in GADT Type Inference
Tracing Ambiguity in GADT Type Inference ML Workshop 2012, Copenhagen Jacques Garrigue & Didier Rémy Nagoya University / INRIA Garrigue & Rémy Tracing ambiguity 1 Generalized Algebraic Datatypes Algebraic
More information3.4 Deduction and Evaluation: Tools Conditional-Equational Logic
3.4 Deduction and Evaluation: Tools 3.4.1 Conditional-Equational Logic The general definition of a formal specification from above was based on the existence of a precisely defined semantics for the syntax
More informationOnce Upon a Polymorphic Type
Once Upon a Polymorphic Type Keith Wansbrough Computer Laboratory University of Cambridge kw217@cl.cam.ac.uk http://www.cl.cam.ac.uk/users/kw217/ Simon Peyton Jones Microsoft Research Cambridge 20 January,
More informationConstrained Types and their Expressiveness
Constrained Types and their Expressiveness JENS PALSBERG Massachusetts Institute of Technology and SCOTT SMITH Johns Hopkins University A constrained type consists of both a standard type and a constraint
More informationFrom Types to Sets in Isabelle/HOL
From Types to Sets in Isabelle/HOL Extented Abstract Ondřej Kunčar 1 and Andrei Popescu 1,2 1 Fakultät für Informatik, Technische Universität München, Germany 2 Institute of Mathematics Simion Stoilow
More informationArbitrary-rank polymorphism in (GHC) Haskell
Arbitrary-rank polymorphism in (GHC) Haskell CAS 743 Stephen Forrest 20 March 2006 Damas-Milner Type System A Damas-Milner type system (also called Hindley-Milner) is a traditional type system for functional
More informationFoundations of AI. 9. Predicate Logic. Syntax and Semantics, Normal Forms, Herbrand Expansion, Resolution
Foundations of AI 9. Predicate Logic Syntax and Semantics, Normal Forms, Herbrand Expansion, Resolution Wolfram Burgard, Andreas Karwath, Bernhard Nebel, and Martin Riedmiller 09/1 Contents Motivation
More informationLecture Notes on Program Equivalence
Lecture Notes on Program Equivalence 15-312: Foundations of Programming Languages Frank Pfenning Lecture 24 November 30, 2004 When are two programs equal? Without much reflection one might say that two
More informationProgramming Languages Third Edition
Programming Languages Third Edition Chapter 12 Formal Semantics Objectives Become familiar with a sample small language for the purpose of semantic specification Understand operational semantics Understand
More informationPolymorphic lambda calculus Princ. of Progr. Languages (and Extended ) The University of Birmingham. c Uday Reddy
06-02552 Princ. of Progr. Languages (and Extended ) The University of Birmingham Spring Semester 2016-17 School of Computer Science c Uday Reddy2016-17 Handout 6: Polymorphic Type Systems 1. Polymorphic
More information3.7 Denotational Semantics
3.7 Denotational Semantics Denotational semantics, also known as fixed-point semantics, associates to each programming language construct a well-defined and rigorously understood mathematical object. These
More informationFormal semantics of loosely typed languages. Joep Verkoelen Vincent Driessen
Formal semantics of loosely typed languages Joep Verkoelen Vincent Driessen June, 2004 ii Contents 1 Introduction 3 2 Syntax 5 2.1 Formalities.............................. 5 2.2 Example language LooselyWhile.................
More informationModular Generic Programming with Extensible Superclasses
Modular Generic Programming with Extensible Superclasses Martin Sulzmann School of Computing, National University of Singapore S16 Level 5, 3 Science Drive 2, Singapore 117543 sulzmann@comp.nus.edu.sg
More informationSimon Peyton Jones Microsoft Research August 2013
Simon Peyton Jones Microsoft Research August 2013 reverse :: a. [a] -> [a] xs :: [Bool] foo :: [Bool] foo = reverse xs Instantiate reverse with a unification variable, standing for an as-yet-unknown type.
More informationAdding GADTs to OCaml the direct approach
Adding GADTs to OCaml the direct approach Jacques Garrigue & Jacques Le Normand Nagoya University / LexiFi (Paris) https://sites.google.com/site/ocamlgadt/ Garrigue & Le Normand Adding GADTs to OCaml 1
More informationDependent Object Types - A foundation for Scala s type system
Dependent Object Types - A foundation for Scala s type system Draft of September 9, 2012 Do Not Distrubute Martin Odersky, Geoffrey Alan Washburn EPFL Abstract. 1 Introduction This paper presents a proposal
More informationSemantics via Syntax. f (4) = if define f (x) =2 x + 55.
1 Semantics via Syntax The specification of a programming language starts with its syntax. As every programmer knows, the syntax of a language comes in the shape of a variant of a BNF (Backus-Naur Form)
More informationLecture #23: Conversion and Type Inference
Lecture #23: Conversion and Type Inference Administrivia. Due date for Project #2 moved to midnight tonight. Midterm mean 20, median 21 (my expectation: 17.5). Last modified: Fri Oct 20 10:46:40 2006 CS164:
More informationCS4215 Programming Language Implementation. Martin Henz
CS4215 Programming Language Implementation Martin Henz Thursday 26 January, 2012 2 Chapter 4 The Language simpl In this chapter, we are exting the language epl in order to provide a more powerful programming
More informationType Checking and Type Inference
Type Checking and Type Inference Principles of Programming Languages CSE 307 1 Types in Programming Languages 2 Static Type Checking 3 Polymorphic Type Inference Version: 1.8 17:20:56 2014/08/25 Compiled
More informationConversion vs. Subtyping. Lecture #23: Conversion and Type Inference. Integer Conversions. Conversions: Implicit vs. Explicit. Object x = "Hello";
Lecture #23: Conversion and Type Inference Administrivia. Due date for Project #2 moved to midnight tonight. Midterm mean 20, median 21 (my expectation: 17.5). In Java, this is legal: Object x = "Hello";
More information1. true / false By a compiler we mean a program that translates to code that will run natively on some machine.
1. true / false By a compiler we mean a program that translates to code that will run natively on some machine. 2. true / false ML can be compiled. 3. true / false FORTRAN can reasonably be considered
More informationExtracting the Range of cps from Affine Typing
Extracting the Range of cps from Affine Typing Extended Abstract Josh Berdine, Peter W. O Hearn Queen Mary, University of London {berdine, ohearn}@dcs.qmul.ac.uk Hayo Thielecke The University of Birmingham
More informationLecture 1 Contracts : Principles of Imperative Computation (Fall 2018) Frank Pfenning
Lecture 1 Contracts 15-122: Principles of Imperative Computation (Fall 2018) Frank Pfenning In these notes we review contracts, which we use to collectively denote function contracts, loop invariants,
More informationCSCI.6962/4962 Software Verification Fundamental Proof Methods in Computer Science (Arkoudas and Musser) Sections p.
CSCI.6962/4962 Software Verification Fundamental Proof Methods in Computer Science (Arkoudas and Musser) Sections 10.1-10.3 p. 1/106 CSCI.6962/4962 Software Verification Fundamental Proof Methods in Computer
More informationBeluga: A Framework for Programming and Reasoning with Deductive Systems (System Description)
Beluga: A Framework for Programming and Reasoning with Deductive Systems (System Description) Brigitte Pientka and Joshua Dunfield McGill University, Montréal, Canada {bpientka,joshua}@cs.mcgill.ca Abstract.
More informationThe Inverse of a Schema Mapping
The Inverse of a Schema Mapping Jorge Pérez Department of Computer Science, Universidad de Chile Blanco Encalada 2120, Santiago, Chile jperez@dcc.uchile.cl Abstract The inversion of schema mappings has
More informationCOS 320. Compiling Techniques
Topic 5: Types COS 320 Compiling Techniques Princeton University Spring 2016 Lennart Beringer 1 Types: potential benefits (I) 2 For programmers: help to eliminate common programming mistakes, particularly
More informationLambda Calculus and Type Inference
Lambda Calculus and Type Inference Björn Lisper Dept. of Computer Science and Engineering Mälardalen University bjorn.lisper@mdh.se http://www.idt.mdh.se/ blr/ August 17, 2007 Lambda Calculus and Type
More informationLambda Calculus and Type Inference
Lambda Calculus and Type Inference Björn Lisper Dept. of Computer Science and Engineering Mälardalen University bjorn.lisper@mdh.se http://www.idt.mdh.se/ blr/ October 13, 2004 Lambda Calculus and Type
More informationA Typed Lambda Calculus for Input Sanitation
A Typed Lambda Calculus for Input Sanitation Nathan Fulton Carthage College nfulton@carthage.edu April 11, 2013 Abstract Programmers often wish to validate or sanitize user input. One common approach to
More informationChapter 3. The While programming language
Chapter 3 The While programming language 1 Contents 3 The While programming language 1 3.1 Big-step semantics........................... 2 3.2 Small-step semantics.......................... 9 3.3 Properties................................
More informationCSCI.6962/4962 Software Verification Fundamental Proof Methods in Computer Science (Arkoudas and Musser) Chapter p. 1/27
CSCI.6962/4962 Software Verification Fundamental Proof Methods in Computer Science (Arkoudas and Musser) Chapter 2.1-2.7 p. 1/27 CSCI.6962/4962 Software Verification Fundamental Proof Methods in Computer
More informationLecture 1 Contracts. 1 A Mysterious Program : Principles of Imperative Computation (Spring 2018) Frank Pfenning
Lecture 1 Contracts 15-122: Principles of Imperative Computation (Spring 2018) Frank Pfenning In these notes we review contracts, which we use to collectively denote function contracts, loop invariants,
More informationLee Pike. June 3, 2005
Proof NASA Langley Formal Methods Group lee.s.pike@nasa.gov June 3, 2005 Proof Proof Quantification Quantified formulas are declared by quantifying free variables in the formula. For example, lem1: LEMMA
More informationJOURNAL OF OBJECT TECHNOLOGY
JOURNAL OF OBJECT TECHNOLOGY Online at www.jot.fm. Published by ETH Zurich, Chair of Software Engineering JOT, 2002 Vol. 1, No. 2, July-August 2002 The Theory of Classification Part 2: The Scratch-Built
More informationConsistent Subtyping for All
Consistent Subtyping for All Ningning Xie Xuan Bi Bruno C. d. S. Oliveira 11 May, 2018 The University of Hong Kong 1 Background There has been ongoing debate about which language paradigm, static typing
More informationSOFTWARE ENGINEERING DESIGN I
2 SOFTWARE ENGINEERING DESIGN I 3. Schemas and Theories The aim of this course is to learn how to write formal specifications of computer systems, using classical logic. The key descriptional technique
More informationLecture Notes on Liveness Analysis
Lecture Notes on Liveness Analysis 15-411: Compiler Design Frank Pfenning André Platzer Lecture 4 1 Introduction We will see different kinds of program analyses in the course, most of them for the purpose
More informationInduction and Semantics in Dafny
15-414 Lecture 11 1 Instructor: Matt Fredrikson Induction and Semantics in Dafny TA: Ryan Wagner Encoding the syntax of Imp Recall the abstract syntax of Imp: a AExp ::= n Z x Var a 1 + a 2 b BExp ::=
More information(Refer Slide Time: 4:00)
Principles of Programming Languages Dr. S. Arun Kumar Department of Computer Science & Engineering Indian Institute of Technology, Delhi Lecture - 38 Meanings Let us look at abstracts namely functional
More informationOverloading, Type Classes, and Algebraic Datatypes
Overloading, Type Classes, and Algebraic Datatypes Delivered by Michael Pellauer Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. September 28, 2006 September 28, 2006 http://www.csg.csail.mit.edu/6.827
More informationReasoning About Set Comprehensions
Reasoning About Set Comprehensions Edmund S L Lam 1 and Iliano Cervesato 1 Carnegie Mellon University sllam@qatarcmuedu, iliano@cmuedu Abstract Set comprehension is a mathematical notation for defining
More informationAdvances in Programming Languages
T O Y H Advances in Programming Languages APL8: Multiparameter Type Classes, Constructor Classes Ian Stark School of Informatics The University of Edinburgh Thursday 4 February Semester 2 Week 4 E H U
More informationChecks and Balances - Constraint Solving without Surprises in Object-Constraint Programming Languages: Full Formal Development
Checks and Balances - Constraint Solving without Surprises in Object-Constraint Programming Languages: Full Formal Development Tim Felgentreff, Todd Millstein, Alan Borning and Robert Hirschfeld Viewpoints
More informationThe Typed λ Calculus and Type Inferencing in ML
Notes on Types S. Arun-Kumar Department of Computer Science and Engineering Indian Institute of Technology New Delhi, 110016 email: sak@cse.iitd.ernet.in April 14, 2002 2 Chapter 1 The Typed λ Calculus
More informationSafe Stratified Datalog With Integer Order Does not Have Syntax
Safe Stratified Datalog With Integer Order Does not Have Syntax Alexei P. Stolboushkin Department of Mathematics UCLA Los Angeles, CA 90024-1555 aps@math.ucla.edu Michael A. Taitslin Department of Computer
More informationComputing Fundamentals 2 Introduction to CafeOBJ
Computing Fundamentals 2 Introduction to CafeOBJ Lecturer: Patrick Browne Lecture Room: K408 Lab Room: A308 Based on work by: Nakamura Masaki, João Pascoal Faria, Prof. Heinrich Hußmann. See notes on slides
More informationThe Encoding Complexity of Network Coding
The Encoding Complexity of Network Coding Michael Langberg Alexander Sprintson Jehoshua Bruck California Institute of Technology Email: mikel,spalex,bruck @caltech.edu Abstract In the multicast network
More informationFunction Symbols in Tuple-Generating Dependencies: Expressive Power and Computability
Function Symbols in Tuple-Generating Dependencies: Expressive Power and Computability Georg Gottlob 1,2, Reinhard Pichler 1, and Emanuel Sallinger 2 1 TU Wien and 2 University of Oxford Tuple-generating
More informationTrees. 3. (Minimally Connected) G is connected and deleting any of its edges gives rise to a disconnected graph.
Trees 1 Introduction Trees are very special kind of (undirected) graphs. Formally speaking, a tree is a connected graph that is acyclic. 1 This definition has some drawbacks: given a graph it is not trivial
More informationLet Arguments Go First
Let Arguments Go First Ningning Xie and Bruno C. d. S. Oliveira The University of Hong Kong {nnxie,bruno}@cs.hku.hk Abstract. Bi-directional type checking has proved to be an extremely useful and versatile
More informationCOMP 181. Agenda. Midterm topics. Today: type checking. Purpose of types. Type errors. Type checking
Agenda COMP 181 Type checking October 21, 2009 Next week OOPSLA: Object-oriented Programming Systems Languages and Applications One of the top PL conferences Monday (Oct 26 th ) In-class midterm Review
More information3 No-Wait Job Shops with Variable Processing Times
3 No-Wait Job Shops with Variable Processing Times In this chapter we assume that, on top of the classical no-wait job shop setting, we are given a set of processing times for each operation. We may select
More informationDerivation of a Pattern-Matching Compiler
Derivation of a Pattern-Matching Compiler Geoff Barrett and Philip Wadler Oxford University Computing Laboratory, Programming Research Group 1986 Introduction This paper presents the derivation of an efficient
More informationIncompatibility Dimensions and Integration of Atomic Commit Protocols
The International Arab Journal of Information Technology, Vol. 5, No. 4, October 2008 381 Incompatibility Dimensions and Integration of Atomic Commit Protocols Yousef Al-Houmaily Department of Computer
More informationSimplifying and Improving Qualified Types
Simplifying and Improving Qualified Types Mark P. Jones Yale University, Department of Computer Science P.O. Box 208285, New Haven, CT 06520-8285. jones-mark@cs.yale.edu Research Report YALEU/DCS/RR-1040,
More informationA system of constructor classes: overloading and implicit higher-order polymorphism
A system of constructor classes: overloading and implicit higher-order polymorphism Mark P. Jones Yale University, Department of Computer Science, P.O. Box 2158 Yale Station, New Haven, CT 06520-2158.
More informationLectures 20, 21: Axiomatic Semantics
Lectures 20, 21: Axiomatic Semantics Polyvios Pratikakis Computer Science Department, University of Crete Type Systems and Static Analysis Based on slides by George Necula Pratikakis (CSD) Axiomatic Semantics
More informationOn the Relationships between Zero Forcing Numbers and Certain Graph Coverings
On the Relationships between Zero Forcing Numbers and Certain Graph Coverings Fatemeh Alinaghipour Taklimi, Shaun Fallat 1,, Karen Meagher 2 Department of Mathematics and Statistics, University of Regina,
More informationHandout 9: Imperative Programs and State
06-02552 Princ. of Progr. Languages (and Extended ) The University of Birmingham Spring Semester 2016-17 School of Computer Science c Uday Reddy2016-17 Handout 9: Imperative Programs and State Imperative
More informationTYPE INFERENCE. François Pottier. The Programming Languages Mentoring ICFP August 30, 2015
TYPE INFERENCE François Pottier The Programming Languages Mentoring Workshop @ ICFP August 30, 2015 What is type inference? What is the type of this OCaml function? let f verbose msg = if verbose then
More informationLecture Notes on Induction and Recursion
Lecture Notes on Induction and Recursion 15-317: Constructive Logic Frank Pfenning Lecture 7 September 19, 2017 1 Introduction At this point in the course we have developed a good formal understanding
More informationFormally-Proven Kosaraju s algorithm
Formally-Proven Kosaraju s algorithm Laurent Théry Laurent.Thery@sophia.inria.fr Abstract This notes explains how the Kosaraju s algorithm that computes the strong-connected components of a directed graph
More informationTypes and Static Type Checking (Introducing Micro-Haskell)
Types and Static (Introducing Micro-Haskell) Informatics 2A: Lecture 13 Alex Simpson School of Informatics University of Edinburgh als@inf.ed.ac.uk 16 October, 2012 1 / 21 1 Types 2 3 4 2 / 21 Thus far
More informationMutable References. Chapter 1
Chapter 1 Mutable References In the (typed or untyped) λ-calculus, or in pure functional languages, a variable is immutable in that once bound to a value as the result of a substitution, its contents never
More informationEncryption as an Abstract Datatype:
June 2003 1/18 Outline Encryption as an Abstract Datatype: an extended abstract Dale Miller INRIA/Futurs/Saclay and École polytechnique 1. Security protocols specified using multisets rewriting. 2. Eigenvariables
More informationCS558 Programming Languages
CS558 Programming Languages Winter 2017 Lecture 7b Andrew Tolmach Portland State University 1994-2017 Values and Types We divide the universe of values according to types A type is a set of values and
More informationVS 3 : SMT Solvers for Program Verification
VS 3 : SMT Solvers for Program Verification Saurabh Srivastava 1,, Sumit Gulwani 2, and Jeffrey S. Foster 1 1 University of Maryland, College Park, {saurabhs,jfoster}@cs.umd.edu 2 Microsoft Research, Redmond,
More informationSemantic Subtyping. Alain Frisch (ENS Paris) Giuseppe Castagna (ENS Paris) Véronique Benzaken (LRI U Paris Sud)
Semantic Subtyping Alain Frisch (ENS Paris) Giuseppe Castagna (ENS Paris) Véronique Benzaken (LRI U Paris Sud) http://www.cduce.org/ Semantic Subtyping - Groupe de travail BD LRI p.1/28 CDuce A functional
More informationTypes and Static Type Checking (Introducing Micro-Haskell)
Types and Static (Introducing Micro-Haskell) Informatics 2A: Lecture 14 John Longley School of Informatics University of Edinburgh jrl@inf.ed.ac.uk 17 October 2017 1 / 21 1 Types 2 3 4 2 / 21 So far in
More informationPart III. Chapter 15: Subtyping
Part III Chapter 15: Subtyping Subsumption Subtype relation Properties of subtyping and typing Subtyping and other features Intersection and union types Subtyping Motivation With the usual typing rule
More informationSORT INFERENCE \coregular" signatures, they derive an algorithm for computing a most general typing for expressions e which is only slightly more comp
Haskell Overloading is DEXPTIME{complete Helmut Seidl Fachbereich Informatik Universitat des Saarlandes Postfach 151150 D{66041 Saarbrucken Germany seidl@cs.uni-sb.de Febr., 1994 Keywords: Haskell type
More informationType Systems COMP 311 Rice University Houston, Texas
Rice University Houston, Texas 1 Type Systems for Programming Language were invented by mathematicians before electronic computers were invented. What is a type? A meaningful subset of the set of the domain
More informationCovered Clause Elimination
Covered Clause Elimination Marijn Heule TU Delft, The Netherlands Matti Järvisalo Univ. Helsinki, Finland Armin Biere JKU Linz, Austria Abstract Generalizing the novel clause elimination procedures developed
More informationProgram Calculus Calculational Programming
Program Calculus Calculational Programming National Institute of Informatics June 21 / June 28 / July 5, 2010 Program Calculus Calculational Programming What we will learn? Discussing the mathematical
More informationProgramming Languages Fall 2014
Programming Languages Fall 2014 Lecture 7: Simple Types and Simply-Typed Lambda Calculus Prof. Liang Huang huang@qc.cs.cuny.edu 1 Types stuck terms? how to fix it? 2 Plan First I For today, we ll go back
More informationTowards a Safe Partial Evaluation of Lazy Functional Logic Programs
WFLP 2007 Towards a Safe Partial Evaluation of Lazy Functional Logic Programs Sebastian Fischer 1 Department of Computer Science, University of Kiel Olshausenstr. 40, D-24098, Kiel, Germany Josep Silva
More informationTerm Algebras with Length Function and Bounded Quantifier Elimination
with Length Function and Bounded Ting Zhang, Henny B Sipma, Zohar Manna Stanford University tingz,sipma,zm@csstanfordedu STeP Group, September 3, 2004 TPHOLs 2004 - p 1/37 Motivation: Program Verification
More informationPrinciples of Programming Languages
Principles of Programming Languages Lesson 14 Type Checking Collaboration and Management Dana Fisman www.cs.bgu.ac.il/~ppl172 1 Type Checking We return to the issue of type safety we discussed informally,
More informationLecture Notes on Static and Dynamic Semantics
Lecture Notes on Static and Dynamic Semantics 15-312: Foundations of Programming Languages Frank Pfenning Lecture 4 September 9, 2004 In this lecture we illustrate the basic concepts underlying the static
More informationOperational Semantics
15-819K: Logic Programming Lecture 4 Operational Semantics Frank Pfenning September 7, 2006 In this lecture we begin in the quest to formally capture the operational semantics in order to prove properties
More informationAn Efficient Staging Algorithm for Binding-Time Analysis
An Efficient Staging Algorithm for Binding-Time Analysis Takuma Murakami 1, Zhenjiang Hu 1,2, Kazuhiko Kakehi 1, and Masato Takeichi 1 1 Department of Mathematical Informatics, Graduate School of Information
More informationMathematical Logic Prof. Arindama Singh Department of Mathematics Indian Institute of Technology, Madras. Lecture - 37 Resolution Rules
Mathematical Logic Prof. Arindama Singh Department of Mathematics Indian Institute of Technology, Madras Lecture - 37 Resolution Rules If some literals can be unified, the same algorithm should be able
More informationOn Meaning Preservation of a Calculus of Records
On Meaning Preservation of a Calculus of Records Emily Christiansen and Elena Machkasova Computer Science Discipline University of Minnesota, Morris Morris, MN 56267 chri1101, elenam@morris.umn.edu Abstract
More informationA Type System for Object Initialization In the Java TM Bytecode Language
Electronic Notes in Theoretical Computer Science 10 (1998) URL: http://www.elsevier.nl/locate/entcs/volume10.html 7 pages A Type System for Object Initialization In the Java TM Bytecode Language Stephen
More informationTopic 3: Propositions as types
Topic 3: Propositions as types May 18, 2014 Propositions as types We have seen that the main mathematical objects in a type theory are types. But remember that in conventional foundations, as based on
More informationType-Safe Update Programming
Type-Safe Update Programming Martin Erwig and Deling Ren Oregon State University Department of Computer Science [erwig rende]@cs.orst.edu Abstract. Many software maintenance problems are caused by using
More informationProving the Correctness of Distributed Algorithms using TLA
Proving the Correctness of Distributed Algorithms using TLA Khushboo Kanjani, khush@cs.tamu.edu, Texas A & M University 11 May 2007 Abstract This work is a summary of the Temporal Logic of Actions(TLA)
More information6.001 Notes: Section 6.1
6.001 Notes: Section 6.1 Slide 6.1.1 When we first starting talking about Scheme expressions, you may recall we said that (almost) every Scheme expression had three components, a syntax (legal ways of
More informationFundamental Concepts. Chapter 1
Chapter 1 Fundamental Concepts This book is about the mathematical foundations of programming, with a special attention on computing with infinite objects. How can mathematics help in programming? There
More information