Constraint-Based Type Inference for Guarded Algebraic Data Types

Size: px
Start display at page:

Download "Constraint-Based Type Inference for Guarded Algebraic Data Types"

Transcription

1 Constraint-Based Type Inference for Guarded Algebraic Data Types Vincent Simonet François Pottier Abstract Guarded algebraic data types, which subsume the concepts known in the literature as indexed types, guarded recursive datatype constructors, and phantom types, and are closely related to inductive types, have the distinguishing feature that, when typechecking a function defined by cases, every branch must be checked under different typing assumptions. This mechanism allows exploiting the presence of dynamic tests in the code to produce extra static type information. We propose an extension of the constraint-based type system HM(X) with pattern matching, guarded algebraic data types, and polymorphic recursion. After establishing a type safety theorem, we show that, up to a few mandatory type annotations, type inference may be reduced to constraint solving. We devote particular attention to keeping the amount of user-supplied type information to a minimum and to ensuring that the generated constraints are efficiently tractable. To the best of our knowledge, this is the first generic and comprehensive account of type inference in the presence of guarded algebraic data types. 1 Introduction Programming languages in the ML family are equipped with algebraic data types and with pattern matching, which provide high-level facilities for defining and manipulating data structures. They also have Hindley-Milner type inference, which allows keeping mandatory type annotations to a minimum. Algebraic data types in ML are simple. Let ε be an algebraic data type constructor, parameterized by a vector of distinct type variables ᾱ. Let K be one of the data constructors associated with ε. The type scheme assigned to K, which may be derived from the declaration of ε, must be of the form K :: ᾱ.τ 1 τ n ε(ᾱ), (1) where n is the arity of K. Then, the typing discipline for pattern matching may summed up as follows: if the pattern K x 1 x n matches a value of type ε(ᾱ), then the variable x i becomes bound to a value of type τ i. INRIA, BP 105, F Le Chesnay Cedex, France. It is possible to imagine extensions of ML where this form is relaxed. Consider, for instance, Läufer and Odersky s extension of ML with existential types [6]. There, the type scheme associated with a data constructor may be of the form K :: ᾱ β.τ 1 τ n ε(ᾱ). (2) The novelty resides in the fact that the argument types τ 1 τ n may contain type variables, namely β, that are not parameters of the algebraic data type constructor ε. Then, the typing discipline for pattern matching becomes: if the pattern K x 1 x n matches a value of type ε(ᾱ), then there exist unknown types β such that the variable x i becomes bound to a value of type τ i. Thus, in this more general setting, algebraic data types subsume existential types. Let us now go one step further by allowing data constructors to be assigned constrained type schemes: K :: ᾱ β[d].τ 1 τ n ε(ᾱ). (3) Here, D is a constraint, that is, a first-order formula built out of predicates on types. In the simplest case, D is a unification constraint, that is, a conjunction of type equations. However, it is also possible to consider more powerful constraint languages; more below. Then, applying K, in order to construct a value of type ε(ᾱ), is possible only if the constraint D is satisfied. In exchange for this restriction, the typing discipline for pattern matching becomes more flexible: if the pattern K x 1 x n matches a value of type ε(ᾱ), then there exist unknown types β such that D is satisfied and the variable x i becomes bound to a value of type τ i. Thus, in this setting, the success of a dynamic test, namely pattern matching, allows extra static type information, namely that expressed by D, to be recovered within the scope of a branch. We refer to this flavor of algebraic data types as guarded, because their data constructors have guarded (constrained) type schemes. Guarded algebraic data types offer a good deal of expressiveness. In the setting of unification constraints, they coincide with inductive types, which allow data constructors to be assigned type schemes of the form K :: β.τ 1 τ n ε( τ). (4) In this form, no constraint is specified, but the type constructor ε may be applied to a vector of arbitrary types, rather than to a vector of distinct type variables ᾱ. It is not difficult to check that the forms (3) and (4) are equivalent. On the one hand, a declaration of the form (4) may

2 be written K :: ᾱ β[ᾱ = τ].τ 1 τ n ε(ᾱ). (5) Conversely, because every satisfiable unification constraint admits a most general unifier, a declaration of the form (3) either has no instance (making K inapplicable, a pathological case) or may be written under the form (4); we omit the details. We refer to the form (3) as inductive types because they are strongly reminiscent of those found in the Calculus of Inductive Constructions [9]. They are also referred to as guarded recursive datatype constructors by Xi, Chen, and Chen [25] and as phantom types by Cheney and Hinze [1]. An instance of this mechanism has been used earlier by Crary, Weirich and Morrisett [2]. Guarded algebraic data types become even more expressive when one leaves the familiar setting of unification and enters the realm of true constraint-based type systems. For instance, they subsume the guarded existential types studied by the first author [13] with structural subtyping constraints in mind. They also subsume singleton types and indexed types. For instance, one may declare the type of integers as a unary guarded algebraic data type constructor, whose parameter is of integer sort, and whose data constructors are the integer constants: k :: α[α = k].int(α) (k Z) This is usually known as a singleton type. One may also declare the type of lists as a binary guarded algebraic data type constructor, whose parameters are respectively of type and integer sorts: Nil :: αβ[β = 0].list(α, β) Cons :: αβ 1β 2[1 + β 1 = β 2].α (list(α, β 1)) list(α, β 2) This is usually known as an indexed type. In practice, in order to exploit these declarations in a useful way, the constraint language must include a fragment of arithmetic in addition to the usual equality or ordering constraints on types. Such constraint-based type systems include Zenger s system of indexed types [27, 28] as well as Xi and Pfenning s system of so-called dependent types [21, 26]. In the particular case of integer manipulations, although it is pleasant to view int as an algebraic data type, standard pattern matching does not quite offer enough expressive power: indeed, in practice, one often wishes to perform two-way comparisons between integers, that is, equality or ordering tests. This may be addressed by extending the grammar of patterns considered here, but is out of the scope of the present paper. We have tried to convince the reader that guarded algebraic data types are a very general notion, that subsumes many known type-theoretic mechanisms. Their usefulness is two-fold. Indeed, increasing the expressiveness of the type system means accepting more programs, thus making new programming idioms available [25, 1], but also allowing more precise type specifications to be written, thus rejecting more programs, in the spirit of refinement types [3, 27, 26]. Thus, it is tempting to extend ML with some flavor of guarded algebraic data types. However, this requires extending Hindley and Milner s type inference discipline as well. The motivation for this paper arose from the realization that no satisfactory account of such an extension exists in the present literature. Indeed, most existing accounts of guarded algebraic data types are written in an explicit style, that is, with type checking, as opposed to type inference, in mind. This includes Cheney and Hinze s [1], an extension of F ω, Xi, Chen, and Chen s [25], an extension of F, as well as earlier works by Xi [21]. Zenger s [27, 28] is written in an implicit, constraint-based style; we believe, however, that it can be made simpler and more general. Xi has implemented Dependent ML [20], an extension of ML that does perform type inference. However, the account given in [21] or [24] is not truly satisfactory. First, the algorithm seems to involve a form of local type inference, since its specification relies on two distinct judgement forms, namely type checking and type synthesis judgements. For this reason, the algorithm appears not to implement a conservative extension of ML. Second, as acknowledged by Xi et al. [25], there is still a conceptual gap between the algorithm s specification and its implementation. Indeed, the latter consists of a constraint generator and a constraint solver, while the former consists of a set of logical typing rules, which do not clearly indicate which constraints are generated. Furthermore, Xi et al. [25] seem to entertain a subtle confusion between checking closed constraints of the form ᾱ.c D, where C and D are conjunction of type equations, and solving constraints that involve implications of the form ᾱ.c D and that have free variables. Only the former is necessary for type checking, while type inference requires the latter, which is more delicate. In the present paper, we propose an extension of the constraint-based type system HM(X) [8] with pattern matching, guarded algebraic data types, and polymorphic recursion; we refer to it as HMG(X). Instances of HMG(X), like those of HM(X), may have subtyping and possibly other primitive constraint forms, which confers great generality to the framework. We establish subject reduction and progress theorems (Section 3), the latter of which is of particular interest, because the criterion for determining whether a pattern matching covers all possible cases is refined using type information. The constraint-based nature of the system makes it easy to reason about type inference: we show that, up to a few mandatory type annotations, it may be reduced to constraint solving (Sections 4 and 5). We devote particular attention to keeping the amount of user-supplied type information to a minimum and to ensuring that the generated constraints are efficiently tractable. Perhaps surprisingly, in the presence of guarded algebraic data types, the inclusion of arbitrarily nested patterns, as opposed to a shallow case construct, complicates the type system and the inference algorithm significantly; it is an important contribution of this paper. We give example program fragments that are well-typed in several instances of HMG(X), which include inductive types, indexed types, and a novel application to dynamic security levels in the context of an information flow analysis (Section 6.3), which involves a form of subtyping. By lack of space, most proofs are omitted; they may be found in the long version of this paper [15]. 2 The untyped calculus This section introduces a call-by-value λ-calculus extended with algebraic data constructors and pattern matching. It is entirely standard, hence we do not explain it in depth. 2.1 Syntax Let x and K range over disjoint denumerable set of program variables and data constructors, respectively. For every data 2

3 dpv(0) = dpv(1) = dpv(x) = {x} dpv(p 1 p 2) = dpv(p 1) dpv(p 2) dpv(p 1 p 2) = dpv(p 1) if dpv(p 1) = dpv(p 2) dpv(k p 1 p n) = dpv(p 1) dpv(p n) nm λ(p 1.e 1 p n.e n ) v [p i v]e i (β) i=1 µx.v [x µx.v]v (µ) let x = v in e [x v]e (let) E[e] E[e ] if e e (context) Figure 1: Variables defined by patterns Figure 3: Operational semantics [1 v] = [p 1 p 2 v] = [p 1 v] [p 2 v] [p 1 p 2 v] = [p 1 v] [p 2 v] [K p 1 p n K v 1 v n ] = [p 1 v 1 ] [p n v n ] Figure 2: Pattern matching constructor K, we assume a fixed nonnegative arity. Then patterns, expressions, clauses, and values are defined as follows: p ::= 0 1 x p p p p K p e ::= x λ c K ē e e µx.v let x = e in e c ::= p.e v ::= λ c K v Patterns include the empty pattern 0, the wildcard pattern 1, variables, conjunction and disjunction patterns, and data constructor applications. To a pattern p, we associate a set of defined program variables dpv(p), as specified in Figure 1. The pattern p is considered ill-formed if dpv(p) is undefined, thus ruling out nonlinear patterns. Expressions include variables, functions, data constructor or function applications, recursive definitions, and local variable definitions. Functions are defined by cases: a λ-abstraction consists of a series of clauses, written λ(c 1,..., c n). A clause c is made up of a pattern p and an expression e, written p.e, where the variables in dpv(p) are considered bound within e. We use ce to stand for a clause or an expression. Values include functions and data structures, that is, applications of a data constructor to values. Within patterns, expressions, and values, all applications of a data constructor must respect its arity: data constructors cannot be partially applied. 2.2 Semantics Whether a pattern p matches a value v is defined by an extended substitution [p v] that is either undefined, which means that p does not match v, or a mapping of dpv(p) to values, which means that p does match v and describes how its variables become bound. Of course, when p is a variable x, the extended substitution [x v] coincides with the regular substitution [x v], which justifies our abuse of notation. Extended substitution for other pattern forms is defined in Figure 2. Let us briefly review the definition. The pattern 0 matches no value, so [0 v] is always undefined. Conversely, the pattern 1 matches every value, but binds no variables, so [1 v] is the empty substitution. In the case of conjunction patterns, stands for set-theoretic disjoint union, so that the bindings produced by p 1 p 2 are the union of those independently produced by p 1 and p 2. The operator is strict that is, its result is undefined if either of K p (p 1 p 2) p K p p 1 p K p p 2 p (p 1 p 2) p (p 1 p) (p 2 p) 1 p p p 1 p 0 p 0 1 p p K p 1 p n K p 1 p n K (p 1 p 1) (p n p n) K p 1 p n K p 1 p n 0 if K K K p 0 p 0 Figure 4: Normalizing patterns its operands is undefined which means that a conjunction pattern matches a value if and only if both its members do. In the case of disjunction patterns, stands for a nonstrict, angelic choice operator with left bias: when o 1 and o 2 are two possibly undefined mathematical objects that belong to the same space when defined, o 1 o 2 stands for o 1 if it is defined and for o 2 otherwise. As a result, a disjunction pattern matches a value if and only if either of its members does. The set of bindings thus produced is that produced by p 1, if defined, otherwise that produced by p 2. Last, the pattern K p 1 p n matches values of the form K v 1 v n only; it matches such a value if and only if every p i matches v i. The call-by-value small-step semantics, written, is defined by the rules of Figure 3. It is standard. Rule (β) governs function application and pattern-matching: the application λ(p 1.e 1 p n.e n)v reduces to [p i v i]e i, where i is the least element of {1,..., n} such that p i matches v. Please note that the application is stuck when no such i exists. The last rule lifts reduction to arbitrary evaluation contexts, whose grammar is the following: E ::= K v [] ē [] e v [] letx = [] in e As a final remark, we note that it is possible to normalize a pattern using the reduction rules given in Figure 4, applied modulo associativity and commutativity of and under arbitrary contexts, without affecting its meaning, as defined above. This normalization process is typically exploited when deciding whether a pattern is empty. We note that, in a normalized pattern, all members of a conjunction but at most one must be variables: hence conjunction reduces to the standard as construct. 3 The type system We now equip our core calculus with a constraint-based type system featuring guarded algebraic datatypes. As is now 3

4 widely recognized, the introduction of constraints is beneficial for at least two reasons: (i) it is pleasant to reduce type inference to constraint solving, even when working within the basic setting of ML; and (ii) this allows moving easily to much more general settings, where constraints may involve Presburger arithmetic, as in DML [21], polynomials, as in Zenger s work [27], subtyping, etc. We present our type system as a conservative extension of HM(X) [8], and refer to it as HMG(X). 3.1 Types and constraints In keeping with the HM(X) tradition, our type system is parameterized by a first-order constraint logic X, whose variables, terms, and formulas are respectively called type variables, types, and constraints. Type variables α, β, γ, δ are drawn from a denumerable set. Given two sets of variables ᾱ and β, we write ᾱ # β for ᾱ β =. We assume a fixed, arbitrary set of algebraic data type constructors ε, each of which is equipped with a nonnegative arity. Then, types τ are built out of type variables using a distinguished function type constructor, algebraic data type constructors (whose arity must be obeyed), and possibly more. Constraints C, D are built out of terms using a distinguished subtyping predicate, the standard first-order connectives, and possibly more. τ ::= α τ 1 τ 2 ε(τ 1,..., τ n)... C, D ::= τ τ C C C α.c... Modulo some syntactic sugar, it is possible to view equality τ = τ, truth true, falsity false, universal quantification α.c, disjunction C C, and implication C C as part of the constraint language. In keeping with the ML tradition, algebraic data types are explicitly declared, but the syntax of such declarations is made more liberal. More precisely, we assume that every data constructor K comes with a closed type scheme of the following form: K :: ᾱ β[d].τ 1 τ n ε(ᾱ) Here, n must be the arity of K, and ᾱ must be a vector of distinct type variables. When K is declared in such a way, we say that it is associated with the algebraic data type constructor ε. In Section 1, we already gave some examples of constructors declarations when introducing Nil and Cons in the context of indexed types, where the constraint language is enriched with arithmetic constraints. Let us also give an example of inductive type, which similar to one of Xi [25]. We assume the data types for integers, int, pairs, α 1 α 2, and lists, list(α), are declared as in ML, and we define the data type ty(α) with three constructors: Int :: α[α = int].ty(α) Pair :: αβ 1β 2[α = β 1 β 2].ty(β 1) ty(β 2) ty(α) List :: αβ[α = list(β)].β ty(α) In short, a value v of type ty(τ) allows representing at runtime the type τ. The constraints carried by the declaration of the constructors allow capturing the relationship between the structure of the value v and that of the type τ: for instance, if v is Int then τ must be int, and if v is Pair v 1 v 2 then τ is τ 1 τ 2, where v 1 (resp. v 2) is the representation of τ 1 (resp. τ 2). In Section 6.1, we will give examples of functions using the data type ty. The logic is interpreted in a model (T, ), a partially ordered set whose elements t are referred to as ground types. Please keep in mind that the interpretation of subtyping may, in particular, be equality. The interpretation is defined, in a standard manner, by a two-place satisfaction predicate ρ C, where ρ is a ground assignment a total mapping of the type variables to ground types and C is a constraint. We write C 1 C 2 if and only if, for every assignment ρ, ρ C 1 implies ρ C 2. We write C 1 C 2 if and only if both C 1 C 2 and C 2 C 1 hold. The interpretation of the standard first-order connectives (that is, their behavior with respect to ) is required to be standard. The interpretation of subtyping is left unspecified, but must satisfy a number of requirements. First, subtyping assertions that involve an arrow type and an algebraic data type, or two algebraic data types with distinct head symbols, must be unsatisfiable. Second, the arrow type constructor must be contravariant in its domain and covariant in its codomain, that is, τ 1 τ 2 τ 1 τ 2 τ 1 τ 1 τ 2 τ 2 must hold. Similarly, every algebraic data type constructor ε must satisfy a family of variance conditions, which may be stated as follows: for every data constructor K associated with ε, if K :: ᾱ β[d].τ 1 τ n ε(ᾱ) and K :: ᾱ β [D ].τ 1 τ n ε(ᾱ ) are two α-equivalent versions of K s declaration, and if β is fresh for every τ i, then D ε(ᾱ ) ε(ᾱ) β.(d iτ i τ i) must hold. This somewhat technical requirement is standard in type systems featuring both subtyping constraints and iso-recursive types, such as our guarded algebraic data types; see e.g. [13]. It is necessary for subject reduction to hold (Lemma 3.5, and may be safely ignored by the reader who is not interested in the details of that particular proof. Let us point out that, if every algebraic data type constructor ε is required to be invariant in every parameter, then every variance condition holds: the proof is not difficult, and relies on the fact that ε(ᾱ ) ε(ᾱ) then entails ᾱ = ᾱ. In particular, in a type system without subtyping, where every type constructor is typically invariant, one need not worry about the variance conditions. 3.2 Typing judgments We now describe three classes of objects that appear in typing judgments: type schemes, environments and environment fragments. As in HM(X), a (constrained) type scheme σ is a pair of a constraint C and a type τ, wrapped within a set of universal quantifiers ᾱ; we write σ ::= ᾱ[c].τ. By abuse of notation, a type τ may be viewed as the type scheme [true].τ. An environment is a mapping from program variables to type schemes; we write dom(γ) for its domain. that is the set of program variables x such that Γ(x) is defined. It is simple if and only if every variable in its domain is in fact mapped to a type, as opposed to an arbitrary type scheme. An environment fragment is a pair of a constraint D and a simple environment Γ, wrapped within a set of existential quantifiers β; we write ::= β[d]γ. The domain of is that of Γ. This notion is new in HMG(X). An environment fragment is meant to describe how crossing a pattern extends the current typing environment. The type system features three distinct typing judgment forms, corresponding to patterns, expressions, and clauses. Typing judgments about patterns are written C p : τ β[d]γ, where the domain of Γ is dpv(p). Such a judgement may be read: under assumption C, it is legal to match a value of type τ against p; furthermore, if such a match is 4

5 successful, then there exist types β that satisfy D such that Γ is a valid description of the values that the variables in dpv(p) receive. Please note that, if the system did not have guarded algebraic data types, then there would be no need for β and D, that is, it would be possible to identify environment fragments with simple environments. For instance, assuming K :: ᾱ.τ 1 τ n ε(ᾱ), the familiar judgment true K x 1 x n : ε(ᾱ) (x 1 τ 1,..., x n τ n ) holds: when matching a value of type ε(ᾱ), the pattern K x 1 x n binds the variable x i to a value of type τ i. Now, going one step further, imagine we have K :: ᾱ β.τ 1 τ n ε(ᾱ). Then, because the type variables β do not appear in the data constructor s result type, the type constructor ε behaves as an existential type: applying K amounts to creating an existential package, while matching against K amounts to opening such a package [6]. Thus, matching against K locally introduces β as a vector of abstract types. In our system, this is reflected by the judgement true K x 1 x n : ε(ᾱ) β(x 1 τ 1,..., x n τ n). In the general case, the declaration of K may involve a constraint D, which bears on the type variables ᾱ and β. Then, a successful match against K not only introduces the abstract types β, but also guarantees that D holds. To keep track of this information, we allow fragments to carry a constraint. For instance, if K :: ᾱ β[d].τ 1 τ n ε(ᾱ) holds, then we have true K x 1 x n : ε(ᾱ) β[d](x 1 τ 1,..., x n τ n). Typing judgments about expressions retain the same form as in HM(X): they are written C,Γ e : σ, where C represents an assumption about judgement s free type variables, Γ assigns type schemes to program variables, and σ is the type scheme assigned to e. Typing judgements about clauses, of the form C,Γ c : τ, are to be interpreted in a similar way. Before moving on, we must introduce some operations on environments and fragments. First, given arbitrary ᾱ, C, and, we write ᾱ.[c] for the fragment ᾱ β[c D]Γ, provided is β[d]γ and β # ftv(ᾱ, C) holds. Second, given environments Γ 1 and Γ 2 with disjoint domains, their conjunction, written Γ 1 Γ 2, is their set-theoretic union. This operation is extended to fragments as follows: given fragments 1 and 2 with disjoint domains, their conjunction 1 2 is the fragment β 1 β2 [D 1 D 2 ](Γ 1 Γ 2 ), provided 1 is β 1 [D 1 ]Γ 1, 2 is β 2 [D 2 ]Γ 2, and β 1 # β 2, β 1 # ftv( 2 ), β 2 # ftv( 1 ) hold. Last, given fragments 1 and 2 with common domain, their disjunction is the fragment β 1 β2 ᾱ[(d 1 Γ Γ 1 ) (D 2 Γ Γ 2 )]Γ, provided 1 is β 1 [D 1 ]Γ 1, 2 is β 2 [D 2 ]Γ 2, provided β 1 # β 2, β 1 # ftv( 2 ), β2 # ftv( 1 ) hold, and provided the environment Γ, whose domain is that of Γ 1 and Γ 2, maps every program variable to a distinct type variable in ᾱ, where ᾱ # β 1 β2. Ignoring the administrative side conditions, it is not difficult to see that these operations on fragments are intended to reflect, at the type level, conjunction and disjunction of patterns. 3.3 Typing rules Whether a typing judgment is valid is defined by the rules in Figure 5, which we now review, beginning with the rules that concern patterns. PatEmpty and PatWild tell that the patterns 0 and 1 may be used at any type, and bind no variables. Because matching against 0 never succeeds, the fragment produced in PatEmpty includes the absurd constraint false. Conversely, because matching against 1 always succeeds, it provides no information; hence, the fragment produced in PatWild includes the tautology true. PatVar is similar to PatWild, except the fragment has nonempty domain. The rule may be read: if the pattern x matches a value of type τ, then the variable x becomes bound to a value of type τ. PatAnd requires both p 1 and p 2 to match values of type τ, producing two fragments 1 and 2 of disjoint domains, because the pattern p 1 p 2 is well-formed; thus, the conjunction 1 2 is defined. Similarly, PatOr requires both p 1 and p 2 to match values of type τ. Furthermore, it requires both to produce the same environment fragment, so that it becomes possible to state that the pattern p 1 p 2 gives rise to, without knowing which of p 1 or p 2 leads to a successful match. With this formulation, disjunction of fragments, which was defined in Section 3.2, is not needed; it is, however, useful later on. PatCstr looks up the declaration of the data constructor K, introducing fresh variables β: the reader may check that β cannot appear free in the rule s conclusion. Then, every p i is checked under a hypothesis augmented with D, so that the type information gained by ensuring that the value at hand is indeed an application of K becomes available when checking that every subpattern is well-typed. Thus, new type information is propagated top-down through the pattern. It is perhaps worth noting that no type information is propagated sideways: for instance, the information gained by ensuring that p 1 matches the value at hand may not be exploited to prove that p 2,..., p n are well-typed. This is apparent in the fact that all subpatterns are checked under a common assumption, namely C D. This design is intentional: we do not wish to commit to a particular strategy (left-to-right or other) concerning the evaluation of pattern matching. The fragment produced by the rule is obtained by fusing the fragments produced by the subpatterns, as in the case of conjunctions, then incorporating the guarded existential quantification β[d][], ensuring that the abstract type variables β remain local. The reader might be surprised by the fact that PatCstr s conclusion assigns type ε(ᾱ) to the pattern, thus requiring the type constructor ε to be applied to a vector of distinct type variables, rather than to a vector of arbitrary types. In fact, in the presence of the non-syntax-directed rules, which we describe next, it is possible to prove that this causes no loss of expressiveness. PatEq allows replacing the type τ with an arbitrary type τ, provided they are provably equal under C. We note that this rule is missing in Xi et al. s treatment [25], causing some reasonable programs that involve nested patterns to be rejected. The rule requires τ = τ, rather than τ τ only: although the latter condition does not compromise type safety, it appears to create complications with type inference. PatFragment allows weakening the fragment produced by a pattern. It employs an auxiliary subsumption judgment, defined as follows. Given fragments and with the same domain, C stands for C D β.(d Γ Γ), provided is β[d]γ, is β [D ]Γ, and β # ftv(c, ), β # ftv(γ ) hold. The constraint Γ Γ is understood pointwise as a conjunction of subtyping constraints. This predicate may be viewed as dual to subsumption of constrained type schemes [17, 10]. In particular, it allows hiding type variables in fragments: for all C, and α, C α. holds, while subsumption of type schemes, on the contrary, allows instantiating type variables: α.σ is more general than σ. PatHide is analogous to Hide, which is discussed below. Let us now briefly review the rules that concern expressions. They are standard, that is, identical to those of 5

6 Patterns (syntax-directed) PatEmpty C 0 : τ [false] PatWild C 1 : τ [true] PatVar C x : τ [true](x τ) PatAnd i {1,2} C p i : τ i C p 1 p 2 : τ 1 2 PatOr i {1,2} C p i : τ C p 1 p 2 : τ PatCstr i C D p i : τ i i K :: ᾱ β[d].τ 1 τ n ε(ᾱ) β # ftv(c) C K p 1 p n : ε(ᾱ) β.[d]( 1 n) Patterns (non-syntax-directed) PatEq C p : τ C τ = τ C p : τ Expressions (syntax-directed) PatFragment C p : τ C C p : τ PatHide C p : τ ᾱ # ftv(τ, ) ᾱ.c p : τ Var Γ(x) = σ C σ C,Γ x : σ Cstr i C,Γ e i : τ i K :: ᾱ β[d].τ 1 τ n ε(ᾱ) C D C,Γ K e 1 e n : ε(ᾱ) Abs i C,Γ ci : τ C,Γ λ(c 1 c n ) : τ App C, Γ e 1 : τ τ C, Γ e 2 : τ C,Γ e 1 e 2 : τ Expressions (non-syntax-directed) Fix C,Γ[x σ] v : σ C,Γ µx.v : σ Let C,Γ e 1 : σ C,Γ[x σ ] e 2 : σ C,Γ letx = e 1 in e 2 : σ Gen C D,Γ e : τ ᾱ # ftv(γ, C) C ᾱ.d,γ e : ᾱ[d].τ Inst C,Γ e : ᾱ[d].τ C D C,Γ e : τ Sub C,Γ e : τ C τ τ C, Γ e : τ Hide C,Γ e : σ ᾱ # ftv(γ, σ) ᾱ.c,γ e : σ Clauses Clause C p : τ β[d]γ C D,ΓΓ e : τ β # ftv(c,γ, τ) C, Γ p.e : τ τ Figure 5: Typing rules HM(X), up to minor cosmetic differences; see e.g. [8, 10]. The second premise of Var ensures that the type scheme extracted from the environment is instantiable under the current hypothesis: σ is a shorthand for the constraint ᾱ.d, provided σ is ᾱ[d].τ. Please also note that our version of Fix allows polymorphic recursion, often an essential feature in programs that involve guarded algebraic data types; this is illustrated in Section 6. Gen performs generalization, turning a type into a type scheme, while Inst performs the converse operation. Sub allows replacing a type τ with an arbitrary type τ, provided the latter is provably a supertype of the former under C. Hide allows making a type variable local to a sub-derivation, which helps managing names, but does not make more programs well-typed. There remains to explain Clause, which assigns a function type τ τ to a clause p.e. The pattern p is checked against the argument type τ, yielding an environment fragment β[d]γ. Then, the expression e is required to have type τ, under an assumption augmented with D and an environment augmented with Γ. By requiring the type variables β to be fresh, the third premise ensures that they remain abstract within e; this condition is identical to that found in the elimination construct for existential types. A key point, here, is the fact that e is typechecked under the augmented constraint C D. The type system exploits the presence of a dynamic check, namely pattern matching, to obtain static information. As a result, in a function defined by cases, each clause may be typechecked under different typing assumptions. It is perhaps interesting to study how the type system degenerates when all data types are regular (as opposed to guarded) algebraic data types, that is, when every data constructor has a declaration of the form K :: ᾱ.τ 1 τ n ε(ᾱ). Then, in every instance of PatCstr, β and D must be and true, respectively, so that the rule may be written: PatCstr i C p i : τ i i K :: ᾱ.τ 1 τ n ε(ᾱ) C K p 1 p n : ε(ᾱ) ( 1 n) Then, it becomes possible to push instances of PatFrag- 6

7 ment and PatHide down through instances of PatCstr. (We let the reader check why this is impossible in general.) Furthermore, when PatFragment or PatHide appears above an instance of Clause, it may be eliminated using a couple of weakening lemmas (see below) or Hide. As a result, it becomes possible to remove PatFragment and PatHide from the system without affecting the set of valid judgments about expressions. It is also worth noting that, once PatCstr is thus simplified and PatFragment is removed, all environment fragments must have the form [true]γ. Thus, typing judgments about patterns may take the form C p : τ Γ, where Γ is a simple environment. Then, Clause may be simplified as follows: Clause C p : τ Γ C,Γ p.e : τ τ C,ΓΓ e : τ This is a standard rule in HM(X): the expression e is typechecked in an environment extended with new bindings, but no fresh variables are introduced, and the constraint assumption remains unchanged. 3.4 Type soundness We now establish several properties of the type system HMG(X), beginning with some standard weakening and normalization lemmas, and culminating with subject reduction and progress theorems. Lemma 3.1 (Weakening) Assume C 1 C 2. C 2 p : τ implies C 1 p : τ and C 2,Γ ce : σ implies C 1,Γ ce : σ. Lemma 3.2 C,Γ e : σ implies C σ. A typing derivation is normal if and only if (a) there are no trivial instances of Inst or Gen, whose premise and conclusion are identical; (b) every instance of Gen appears either at the root of the derivation or as a premise of a syntaxdirected rule; and (c) every instance of Hide appears either at the root of the derivation or as a premise of Gen. Lemma 3.3 (Normalization) Every valid typing judgment admits a normal derivation. We now prove that HMG(X) is sound, following Wright and Felleisen s syntactic approach [19]. We establish a few technical results, then give subject reduction and progress theorems. Lemma 3.4 (Substitution) C, Γ[x σ ] ce : σ and C, v : σ imply C,Γ [x v]ce : σ. Next comes the key technical lemma that helps establishing subject reduction for pattern matching. Its statement is somewhat involved: perhaps it is worth explaining it first in the simple case where β is empty and D is true. Then, H must be C, so the lemma s conclusion becomes: for every x dpv(p), C, [p v]x : Γ(x) holds. In other words, the value that x receives when p matches v does indeed have the predicted type. In the general case, the statement must be made more complex, in order to account for the abstract types β. It is still true that [p v]x has type Γ(x), albeit under a constraint H, which extends C with information about the type variables β, as stated by the property C β.h. The exact amount of extra information carried by H is unknown, but is strong enough to guarantee that D holds, as stated by the property H D. (0) = 1 (1) = 0 (x) = 0 (K p 1 p n) = ( i [1,n] K p 1 p i 1 ( p i) p i+1 p n) ( K K,K K K 1 1) (p 1 p 2) = ( p 1) ( p 2) (p 1 p 2) = ( p 1) ( p 2) Figure 6: Computing the complement of a pattern Lemma 3.5 Assume v matches p and C, v : τ and C p : τ hold. Write as β[d]γ, where β # ftv(c). Then, there exists a constraint H such that H D and C β.h and, for every x dpv(p), H, [p v]x : Γ(x) holds. Using the previous lemma, we may prove subject reduction. Theorem 3.1 (Subject reduction) C, e : σ and e e imply C, e : σ. Proof. By Lemma 3.3, we may assume that the derivation of C, e : σ (1) is normal. Moreover, we may restrict our attention to the case where it ends with an instance of a syntax-directed rule; indeed, the general case follows immediately. We proceed by induction on the derivation of e e. Case (β). e is λ(p 1.e 1 p n.e n)v and e is [p i v]e i, for some i {1,..., n}. The derivation of (1) ends with an instance of App whose premises are C, λ(p 1.e 1 p n.e n) : τ τ (2) and C, v : τ (3), where σ is τ. Because Sub may be pushed up through Abs, we may assume that the derivation of (2) ends with an instance of Abs, whose premises include C, p i.e i : τ τ (4). The derivation of (4) ends with an instance of Clause whose premises are C p i : τ β[d]γ (5) and C D, Γ e i : τ (6) and β # ftv(c, τ) (7). By (3), (5), (7), and Lemma 3.5, there exists H such that H D (8) and C β.h (9) and, for every x dpv(p i), H, [p i v i]x : Γ(x) (10) holds. By (9), we have H C; together with (8), this implies H C D. Thus, applying Lemma 3.1 to (6), we find H,Γ e i : τ (11). By Lemma 3.4, (10) and (11) imply H, [p i v i ]e i : τ (12). Applying Hide to (12) and (7) and exploiting (9), we obtain C, [p i v i ]e i : τ. Case (µ). e is µx.v and e is [x µx.v]v. The derivation of (1) ends with an instance of Fix whose premise is C,(x σ) v : σ. The result follows by Lemma 3.4. Case (let). e is letx = v in e 1 and e is [x v]e 1. The derivation of (1) must end with an instance of Let, whose premises are C, v : σ and C,(x σ ) e 1 : σ. The result follows by Lemma 3.4. Case (context). By the induction hypothesis. We now turn to the proof of the progress theorem. In languages equipped with pattern matching, such as ML, it is well-known that well-typedness alone is not sufficient to ensure progress: indeed, a well-typed β-redex (λp 1.e 1 p n.e n) v may still be irreducible if none of p 1,..., p n matches v. For this reason, we first establish progress under the assumption that every case analysis is exhaustive, as determined by a simple syntactic criterion. Then, we show how, in the presence of guarded algebraic 7

8 data types, this criterion may be refined so as to take type information into account. Our syntactic criterion for exhaustiveness is standard: it is identical to that of ML. It uses almost no type information: it only requires being able to determine whether or not two data constructors K and K are associated with the same algebraic data type ε. (We write K K when they are.) It relies on a notion of pattern negation or complement, which is standard [23] and whose definition is recalled in Figure 6. A case analysis λ(p 1.e 1 p n.e n) is said to be exhaustive if and only if the pattern (p 1 p n) is equivalent to 0. Pattern equivalence may be defined as follows: p 1 and p 2 are equivalent if and only if the functions [p 1 ] and [p 2 ] coincide. One may prove that p is equivalent to 0 if and only if p 0 holds (Figure 4). It is important to note that the pattern p p is not in general equivalent to 1: this is due to the definition of (K p 1 p n), where only the data constructors compatible with K are enumerated. The next lemma uses the type system to work around this difficulty: if p has type τ, then p p matches every value of type τ. The hypotheses of this lemma are identical to those of Lemma 3.5; it is, however, oriented towards proving progress, rather than subject reduction. Lemma 3.6 If C, v : τ and C p : τ hold, where C is satisfiable, then v matches p p. An expression e is well-typed if and only if C, e : σ holds for some satisfiable constraint C. Theorem 3.2 (Progress) If e is well-typed and contains exhaustive case analyses only, then it is either reducible or a value. A closed expression e is said to go wrong if there exists an irreducible expression e that is not a value such that e e. We may now state a first type soundness result: Theorem 3.3 (Type soundness) If e is well-typed and contains exhaustive case analyses only, then it does not go wrong. In ML, rejecting nonexhaustive case analyses is considered acceptable. In the presence of guarded algebraic data types, however, this purely syntactic criterion becomes somewhat unsatisfactory: although it is correct, we can do better. Indeed, the type assigned to a function may allow determining that some branches can never be taken: this is what Xi [22] refers as dead code elimination. For instance, the function λ(list x).x is not exhaustive, as per our syntactic criterion, because (List x) is Int Pair 1, which is nonempty (the declaration of the data constructors Int, Pair and List, associated with the data type ty, were given in Section 3.1). However, if the function is used at type ty(list(τ)) ty(τ), then pattern matching cannot fail, because Int Pair 1 cannot match a value of type ty(list(τ)). In order to allow type information to be exploited in this way, we proceed as follows: prior to typechecking, we automatically complete every case analysis with dummy branches, which produce a runtime error if taken. Thus, every case analysis becomes exhaustive by construction. Then, we typecheck the new program. If it is well-typed, then we have, in effect, proved that the newly inserted branches can never be taken. More precisely, let be a new expression, whose typing rule is false,γ : σ. Let be the procedure that completes every case analysis with dummy branches: λ(p 1.e 1 p n.e n ) is λ(p 1. e 1 p n. e n (p 1 p n ). ), and is a homomorphism with respect to all other expression forms. Since may be typed only under an absurd assumption, proving that the new program is welltyped ensures that no newly inserted branch may be taken. Theorem 3.4 (Type soundness, revisited) If e well-typed, then e does not go wrong. Note that we typecheck e, but still obtain type soundness for the original program e. The ideas presented here concerning exhaustiveness and dead code elimination are not new: see [22, 23]. However, a formal type soundness statement for a type system equipped with guarded algebraic data types does not seem to exist in the current literature; Theorem 3.4 fills this gap. Normalizing patterns as per the rules of Figure 4 and resolving sequentiality [23] may improve the accuracy of type checking in the presence of guarded algebraic data types. In particular, in the procedure described above, the pattern (p 1 p n ) must be normalized in order to ensure that our refined approach is at least as expressive as the purely syntactic criterion. Indeed, consider a function e = λ(p 1.e 1 p n.e n ), and assume it is exhaustive, that is, (p 1 p n ) is empty. Then, applying the above procedure, we have (p 1 p n ) 0, so e is e = λ(p 1. e 1 p n. e n 0. ). Then, because C,Γ 0. : τ 1 τ 2 holds for all C, Γ, τ 1 and τ 2, one may check that e and e admit the same typings. 4 Type inference We now turn to type inference, with the aim of reducing it to constraint solving. We immediately point out that, because HMG(X) has polymorphic recursion, well-typedness in it is most likely undecidable [4]. Thus, to begin, we restrict the language by requiring every µ-bound variable to be explicitly annotated with a type scheme. Furthermore, for reasons that will become in apparent in Section 5, it is also useful that every λ-abstraction be annotated with a type scheme. Since, in practice, the µ binder is used to define functions only, we may just as well merge the two constructs, so as to require a single type annotation. Thus, the language of expressions becomes: e ::= x µ(x : β.σ).λ c K ē e e let x = e in e Instead of requiring σ to be closed, we allow it to have free type variables, which must be included in β, so that the type annotation, as a whole, is closed. (It would be possible to suppress β, allowing σ s free type variables to be bound elsewhere, but that is arguably an orthogonal issue.) Not requiring σ to be closed is important, for several reasons. One is that, thanks to this design choice, only functions that are polymorphically recursive must be annotated. Indeed, we may now define µx.λ c as syntactic sugar for µ(x: β 1β 2.β 1 β 2).λ c. Then, the type inference system will infer a monomorphic function type for x, as in ML. Another reason is that local functions do not in general admit a closed type scheme: this is illustrated in Section 6. The typing rules Abs and Fix are replaced with the following new rule, a combination of Abs, Gen, and Fix, where the type scheme assigned to x is taken from the annotation instead of being guessed. This is the key point that makes is 8

9 type inference decidable again. FixAbs i C D,Γ[x σ] c i : τ ᾱ # ftv(c,γ) σ = ᾱ[d].τ C ᾱ.d,γ µ(x : β.σ).λ c : σ The modified type system is a restriction of HMG(X), so it is still sound. In the following, we show that type inference for it may be reduced to constraint solving. For the sake of simplicity, we require every annotation to be of the form β. γ[c].τ 1 τ 2, that is, to syntactically present an arrow type. We begin our treatment of type inference by defining a procedure that computes principal typing judgments for patterns. It consists of two functions of a pattern p and a type τ, given in Figure 7. (As usual, the variables that appear bound in the right-hand side of an equation must be chosen fresh for the parameters that appear on its left-hand side.) The constraint p : τ is meant to express that it is legal to test whether p matches a value of type τ, while the fragment p : τ is intended to represent knowledge about the bindings that arise when such a test succeeds. This explanation is made more precise by the next two lemmas: they state that the procedure gives rise to judgments that are both correct and principal. Lemma 4.1 (Correctness) p : τ p : τ p : τ. Lemma 4.2 (Completeness) If C p : τ then C p : τ and C p : τ. Of particular interest is the last rule in the left column, which may be read as follows: it is legal to apply p to a value of type τ if and only if, for some types ᾱ, τ is of the form ε(ᾱ) and, for all types β that satisfy D and for every i [1, n], it is legal to apply p i to a value of type τ i. The use of universal quantification and of implication encodes the fact that the types β must be considered abstract, but may safely be assumed to satisfy D. The penultimate rule in the right column uses the fragment disjunction operator + to compute a least upper bound of the fragments associated with p 1 and p 2. Let us now turn to expressions and clauses. Given an environment Γ, an expression e and an expected type τ, the constraint Γ e : τ, defined in Figure 8, represents a necessary and sufficient condition for e to have type τ under environment Γ. This is made precise by the next two theorems. Theorem 4.1 (Correctness) Γ ce : τ,γ ce : τ. Theorem 4.2 (Completeness) C, Γ ce : ᾱ[d].τ and ᾱ # ftv(γ) imply C ᾱ.d Γ ce : τ. Using Theorems 4.1 and 4.2, as well as Lemma 3.2, it is easy to prove that e is well-typed under environment Γ if and only if the constraint α. Γ e : α is satisfiable. Thus, we have reduced type inference to constraint solving. Many of the constraint generation rules in Figure 8 are standard; see e.g. [16, 13]. In the first rule, provided ᾱ # ftv(τ ) holds, we write ᾱ[d].τ τ for ᾱ.(d τ τ ). The rule requires the expected type τ to be an instance of the type scheme Γ(x). The third rule ensures that the domain type of the function e 1 matches the type of the argument e 2 by using the fresh type variable α to stand for both of them. The second rule may be read as a particular case of the first and third rules, where the type scheme associated with K is fixed instead of found in the environment. The fifth rule deals with let-polymorphism. Somewhat more novel are the fourth and last rules. The former implements polymorphic recursion by ensuring that the clauses c have type scheme σ under the hypothesis that x has type scheme σ. The prefix γ.c [] is used to encode this requirement. (We let Γ[x σ] c : τ 1 τ 2 stand for i Γ[x σ] c i : τ 1 τ 2, provided c is (c 1,..., c n).) The expected type τ is required to be an instance of σ. The type variables β, whose value was not specified by the user, are existentially bound, so it is up to the constraint solver to determine their value. For unannotated functions of the form µx.λ c, which were defined at the beginning of Section 4, this gives rise to the following derived rule: Γ µ(x: β 1β 2.β 1 β 2).λ c : τ is β 1β 2.( Γ[x β 1 β 2] c : β 1 β 2 β 1 β 2 τ). The last rule deals with clauses as follows. First, the function s domain type is required to match the pattern s type, via the constraint p : τ 1. Then, the clause s body e is required to have type τ 2 under a context extended with new abstract types β, a new typing hypothesis D, and an extended environment Γ, all three of which are obtained by evaluating p : τ 1. Type inference for HM(X) is usually reduced to constraint solving for a logic that includes primitive predicates (such as subtyping), conjunction, and existential quantification. Here, we make use of more first-order connectives, including universal quantification and implication. Nevertheless, this is enough to show that type inference for some instances of HMG(X) is decidable. For instance, assuming no predicates other than subtyping are available, and assuming subtyping is structural (which includes the case where subtyping is in fact equality), constraint solving is decidable [5]. However, such a result remains weak, because the complexity of constraint solving for the first-order theory of equality is nonelementary. To strengthen our result, we must work a bit more and ensure that we actually generate tractable constraints. 5 Tractable type inference What are the sources of complexity in the constraints that we generate? One is that we have made the whole constraint language available to the user, in data constructor declarations and in type annotations. To address this issue, we now forbid the use of negation in user-supplied constraints, so that only primitive predicates, conjunction, and existential quantification are made available to the user, as in HM(X). Another is our use of logical disjunction (hidden inside the fragment disjunction operator +) in the treatment of disjunction patterns. Every such use of disjunction must appear to the left of an implication in the generated constraint, so it is possible to lift it up and out of the implication, turning it into a conjunction. In fact, this somewhat naïve treatment corresponds to eliminating disjunction patterns in the source program, at the cost of some (possibly exponential) code duplication, as done by Xi [23]. We do not have a fundamentally better solution to this issue at the time being. The last source of complexity, which we are most interested in, is our frequent use of combined universal quantification and implication prefixes, of the form β.d []. If uncontrolled, these allow encoding negation ( D is D false). However, it turns out that, with some 9

Where is ML type inference headed?

Where 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 information

Constraint-Based Type Inference for Guarded Algebraic Data Types

Constraint-Based Type Inference for Guarded Algebraic Data Types INSTITUT NATIONAL DE RECHERCHE EN INFORMATIQUE ET EN AUTOMATIQUE Constraint-Based Type Inference for Guarded Algebraic Data Types Vincent Simonet François Pottier N 5462 Janvier 2005 Thème SYM apport de

More information

Simple Unification-based Type Inference for GADTs

Simple 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 information

Goal. CS152: Programming Languages. Lecture 15 Parametric Polymorphism. What the Library Likes. What The Client Likes. Start simpler.

Goal. CS152: Programming Languages. Lecture 15 Parametric Polymorphism. What the Library Likes. What The Client Likes. Start simpler. Goal Understand what this interface means and why it matters: CS152: Programming Languages Lecture 15 Parametric Polymorphism Dan Grossman Spring 2011 type a mylist; val mt_list : a mylist val cons : a

More information

CS152: Programming Languages. Lecture 11 STLC Extensions and Related Topics. Dan Grossman Spring 2011

CS152: Programming Languages. Lecture 11 STLC Extensions and Related Topics. Dan Grossman Spring 2011 CS152: Programming Languages Lecture 11 STLC Extensions and Related Topics Dan Grossman Spring 2011 Review e ::= λx. e x e e c v ::= λx. e c τ ::= int τ τ Γ ::= Γ, x : τ (λx. e) v e[v/x] e 1 e 1 e 1 e

More information

Let Arguments Go First

Let 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 information

Arbitrary-rank polymorphism in (GHC) Haskell

Arbitrary-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 information

Adding GADTs to OCaml the direct approach

Adding 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 information

CSE-321 Programming Languages 2011 Final

CSE-321 Programming Languages 2011 Final Name: Hemos ID: CSE-321 Programming Languages 2011 Final Prob 1 Prob 2 Prob 3 Prob 4 Prob 5 Prob 6 Total Score Max 15 15 10 17 18 25 100 There are six problems on 18 pages in this exam, including one extracredit

More information

The Typed λ Calculus and Type Inferencing in ML

The 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 information

ML F Raising ML to the Power of System F

ML F Raising ML to the Power of System F ML F Raising ML to the Power of System F Didier Le Botlan and Didier Rémy INRIA-Rocquencourt 78153 Le Chesnay Cedex, France {Didier.Le_Botlan,Didier.Remy}@inria.fr Abstract We propose a type system ML

More information

(Refer Slide Time: 4:00)

(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 information

COS 320. Compiling Techniques

COS 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 information

A proof-producing CSP solver: A proof supplement

A proof-producing CSP solver: A proof supplement A proof-producing CSP solver: A proof supplement Report IE/IS-2010-02 Michael Veksler Ofer Strichman mveksler@tx.technion.ac.il ofers@ie.technion.ac.il Technion Institute of Technology April 12, 2010 Abstract

More information

1 Introduction. 3 Syntax

1 Introduction. 3 Syntax CS 6110 S18 Lecture 19 Typed λ-calculus 1 Introduction Type checking is a lightweight technique for proving simple properties of programs. Unlike theorem-proving techniques based on axiomatic semantics,

More information

Review. CS152: Programming Languages. Lecture 11 STLC Extensions and Related Topics. Let bindings (CBV) Adding Stuff. Booleans and Conditionals

Review. CS152: Programming Languages. Lecture 11 STLC Extensions and Related Topics. Let bindings (CBV) Adding Stuff. Booleans and Conditionals Review CS152: Programming Languages Lecture 11 STLC Extensions and Related Topics e ::= λx. e x ee c v ::= λx. e c (λx. e) v e[v/x] e 1 e 2 e 1 e 2 τ ::= int τ τ Γ ::= Γ,x : τ e 2 e 2 ve 2 ve 2 e[e /x]:

More information

Typed Lambda Calculus

Typed Lambda Calculus Department of Linguistics Ohio State University Sept. 8, 2016 The Two Sides of A typed lambda calculus (TLC) can be viewed in two complementary ways: model-theoretically, as a system of notation for functions

More information

Hiding local state in direct style: a higher-order anti-frame rule

Hiding local state in direct style: a higher-order anti-frame rule 1 / 65 Hiding local state in direct style: a higher-order anti-frame rule François Pottier January 28th, 2008 2 / 65 Contents Introduction Basics of the type system A higher-order anti-frame rule Applications

More information

A modern eye on ML type inference Old techniques and recent developments. François Pottier INRIA

A modern eye on ML type inference Old techniques and recent developments. François Pottier INRIA A modern eye on ML type inference Old techniques and recent developments François Pottier INRIA September 2005 1 Abstract Hindley and Milner s type system is at the heart of programming languages such

More information

Polymorphic Typed Defunctionalization

Polymorphic Typed Defunctionalization Polymorphic Typed Defunctionalization François Pottier Francois.Pottier@inria.fr Nadji Gauthier Nadji.Gauthier@inria.fr Abstract Defunctionalization is a program transformation that aims to turn a higher-order

More information

From Types to Sets in Isabelle/HOL

From 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 information

CSCI.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 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 information

Programming Languages Third Edition

Programming 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 information

Lambda Calculus and Type Inference

Lambda 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 information

CS 6110 S11 Lecture 25 Typed λ-calculus 6 April 2011

CS 6110 S11 Lecture 25 Typed λ-calculus 6 April 2011 CS 6110 S11 Lecture 25 Typed λ-calculus 6 April 2011 1 Introduction Type checking is a lightweight technique for proving simple properties of programs. Unlike theorem-proving techniques based on axiomatic

More information

Programming Languages Lecture 14: Sum, Product, Recursive Types

Programming Languages Lecture 14: Sum, Product, Recursive Types CSE 230: Winter 200 Principles of Programming Languages Lecture 4: Sum, Product, Recursive Types The end is nigh HW 3 No HW 4 (= Final) Project (Meeting + Talk) Ranjit Jhala UC San Diego Recap Goal: Relate

More information

Mutable References. Chapter 1

Mutable 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 information

Extracting the Range of cps from Affine Typing

Extracting 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 information

3.7 Denotational Semantics

3.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 information

Type Checking and Type Inference

Type 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 information

Foundations 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 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 information

Flang typechecker Due: February 27, 2015

Flang typechecker Due: February 27, 2015 CMSC 22610 Winter 2015 Implementation of Computer Languages I Flang typechecker Due: February 27, 2015 Project 3 February 9, 2015 1 Introduction The third project is to implement a type checker for Flang,

More information

Programming Languages Lecture 15: Recursive Types & Subtyping

Programming Languages Lecture 15: Recursive Types & Subtyping CSE 230: Winter 2008 Principles of Programming Languages Lecture 15: Recursive Types & Subtyping Ranjit Jhala UC San Diego News? Formalize first-order type systems Simple types (integers and booleans)

More information

The Typed Racket Guide

The Typed Racket Guide The Typed Racket Guide Version 5.3.6 Sam Tobin-Hochstadt and Vincent St-Amour August 9, 2013 Typed Racket is a family of languages, each of which enforce

More information

CS-XXX: Graduate Programming Languages. Lecture 9 Simply Typed Lambda Calculus. Dan Grossman 2012

CS-XXX: Graduate Programming Languages. Lecture 9 Simply Typed Lambda Calculus. Dan Grossman 2012 CS-XXX: Graduate Programming Languages Lecture 9 Simply Typed Lambda Calculus Dan Grossman 2012 Types Major new topic worthy of several lectures: Type systems Continue to use (CBV) Lambda Caluclus as our

More information

Meta-programming with Names and Necessity p.1

Meta-programming with Names and Necessity p.1 Meta-programming with Names and Necessity Aleksandar Nanevski Carnegie Mellon University ICFP, Pittsburgh, 05 October 2002 Meta-programming with Names and Necessity p.1 Meta-programming Manipulation of

More information

Tradeoffs. CSE 505: Programming Languages. Lecture 15 Subtyping. Where shall we add useful completeness? Where shall we add completeness?

Tradeoffs. CSE 505: Programming Languages. Lecture 15 Subtyping. Where shall we add useful completeness? Where shall we add completeness? Tradeoffs CSE 505: Programming Languages Lecture 15 Subtyping Zach Tatlock Autumn 2017 Desirable type system properties (desiderata): soundness - exclude all programs that get stuck completeness - include

More information

CS 6110 S14 Lecture 1 Introduction 24 January 2014

CS 6110 S14 Lecture 1 Introduction 24 January 2014 CS 6110 S14 Lecture 1 Introduction 24 January 2014 1 Introduction What is a program? Is it just something that tells the computer what to do? Yes, but there is much more to it than that. The basic expressions

More information

Typed Racket: Racket with Static Types

Typed Racket: Racket with Static Types Typed Racket: Racket with Static Types Version 5.0.2 Sam Tobin-Hochstadt November 6, 2010 Typed Racket is a family of languages, each of which enforce that programs written in the language obey a type

More information

CSE-321 Programming Languages 2014 Final

CSE-321 Programming Languages 2014 Final Name: Hemos ID: CSE-321 Programming Languages 2014 Final Problem 1 Problem 2 Problem 3 Problem 4 Problem 5 Problem 6 Total Score Max 15 12 14 14 30 15 100 There are six problems on 12 pages in this exam.

More information

Lecture 9: Typed Lambda Calculus

Lecture 9: Typed Lambda Calculus Advanced Topics in Programming Languages Spring Semester, 2012 Lecture 9: Typed Lambda Calculus May 8, 2012 Lecturer: Mooly Sagiv Scribe: Guy Golan Gueta and Shachar Itzhaky 1 Defining a Type System for

More information

Tracing Ambiguity in GADT Type Inference

Tracing 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 information

Topic 3: Propositions as types

Topic 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 information

The Encoding Complexity of Network Coding

The 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 information

Calculus of Inductive Constructions

Calculus of Inductive Constructions Calculus of Inductive Constructions Software Formal Verification Maria João Frade Departmento de Informática Universidade do Minho 2008/2009 Maria João Frade (DI-UM) Calculus of Inductive Constructions

More information

CMSC 336: Type Systems for Programming Languages Lecture 5: Simply Typed Lambda Calculus Acar & Ahmed January 24, 2008

CMSC 336: Type Systems for Programming Languages Lecture 5: Simply Typed Lambda Calculus Acar & Ahmed January 24, 2008 CMSC 336: Type Systems for Programming Languages Lecture 5: Simply Typed Lambda Calculus Acar & Ahmed January 24, 2008 Contents 1 Solution to the Exercise 1 1.1 Semantics for lambda calculus.......................

More information

Harvard School of Engineering and Applied Sciences CS 152: Programming Languages

Harvard School of Engineering and Applied Sciences CS 152: Programming Languages Harvard School of Engineering and Applied Sciences CS 152: Programming Languages Lecture 14 Tuesday, March 24, 2015 1 Parametric polymorphism Polymorph means many forms. Polymorphism is the ability of

More information

Typed Lambda Calculus for Syntacticians

Typed Lambda Calculus for Syntacticians Department of Linguistics Ohio State University January 12, 2012 The Two Sides of Typed Lambda Calculus A typed lambda calculus (TLC) can be viewed in two complementary ways: model-theoretically, as a

More information

Lecture Notes on Data Representation

Lecture Notes on Data Representation Lecture Notes on Data Representation 15-814: Types and Programming Languages Frank Pfenning Lecture 9 Tuesday, October 2, 2018 1 Introduction In this lecture we ll see our type system in action. In particular

More information

LOGIC AND DISCRETE MATHEMATICS

LOGIC AND DISCRETE MATHEMATICS LOGIC AND DISCRETE MATHEMATICS A Computer Science Perspective WINFRIED KARL GRASSMANN Department of Computer Science University of Saskatchewan JEAN-PAUL TREMBLAY Department of Computer Science University

More information

4.5 Pure Linear Functional Programming

4.5 Pure Linear Functional Programming 4.5 Pure Linear Functional Programming 99 4.5 Pure Linear Functional Programming The linear λ-calculus developed in the preceding sections can serve as the basis for a programming language. The step from

More information

1.3. Conditional expressions To express case distinctions like

1.3. Conditional expressions To express case distinctions like Introduction Much of the theory developed in the underlying course Logic II can be implemented in a proof assistant. In the present setting this is interesting, since we can then machine extract from a

More information

An Implementation of the Language Lambda Prolog Organized around Higher-Order Pattern Unification

An Implementation of the Language Lambda Prolog Organized around Higher-Order Pattern Unification An Implementation of the Language Lambda Prolog Organized around Higher-Order Pattern Unification SUBMITTED TO THE FACULTY OF THE GRADUATE SCHOOL OF THE UNIVERSITY OF MINNESOTA BY Xiaochu Qi IN PARTIAL

More information

TYPE INFERENCE. François Pottier. The Programming Languages Mentoring ICFP August 30, 2015

TYPE 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 information

The Metalanguage λprolog and Its Implementation

The Metalanguage λprolog and Its Implementation The Metalanguage λprolog and Its Implementation Gopalan Nadathur Computer Science Department University of Minnesota (currently visiting INRIA and LIX) 1 The Role of Metalanguages Many computational tasks

More information

Harvard School of Engineering and Applied Sciences Computer Science 152

Harvard School of Engineering and Applied Sciences Computer Science 152 Harvard School of Engineering and Applied Sciences Computer Science 152 Lecture 17 Tuesday, March 30, 2010 1 Polymorph means many forms. Polymorphism is the ability of code to be used on values of different

More information

Type assignment for intersections and unions in call-by-value languages

Type assignment for intersections and unions in call-by-value languages Type assignment for intersections and unions in call-by-value languages Joshua Dunfield and Frank Pfenning Triple Project Carnegie Mellon University 8 April 2003 FOSSACS 03, Warsaw, Poland Type assignment

More information

A Typed Lambda Calculus for Input Sanitation

A 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 information

Subtyping. Lecture 13 CS 565 3/27/06

Subtyping. Lecture 13 CS 565 3/27/06 Subtyping Lecture 13 CS 565 3/27/06 Polymorphism Different varieties of polymorphism: Parametric (ML) type variables are abstract, and used to encode the fact that the same term can be used in many different

More information

This is already grossly inconvenient in present formalisms. Why do we want to make this convenient? GENERAL GOALS

This is already grossly inconvenient in present formalisms. Why do we want to make this convenient? GENERAL GOALS 1 THE FORMALIZATION OF MATHEMATICS by Harvey M. Friedman Ohio State University Department of Mathematics friedman@math.ohio-state.edu www.math.ohio-state.edu/~friedman/ May 21, 1997 Can mathematics be

More information

Lecture Notes on Aggregate Data Structures

Lecture Notes on Aggregate Data Structures Lecture Notes on Aggregate Data Structures 15-312: Foundations of Programming Languages Frank Pfenning Lecture 8 September 23, 2004 In this lecture we discuss various language extensions which make MinML

More information

CS4215 Programming Language Implementation. Martin Henz

CS4215 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 information

Subsumption. Principle of safe substitution

Subsumption. Principle of safe substitution Recap on Subtyping Subsumption Some types are better than others, in the sense that a value of one can always safely be used where a value of the other is expected. Which can be formalized as by introducing:

More information

LTCS Report. Concept Descriptions with Set Constraints and Cardinality Constraints. Franz Baader. LTCS-Report 17-02

LTCS Report. Concept Descriptions with Set Constraints and Cardinality Constraints. Franz Baader. LTCS-Report 17-02 Technische Universität Dresden Institute for Theoretical Computer Science Chair for Automata Theory LTCS Report Concept Descriptions with Set Constraints and Cardinality Constraints Franz Baader LTCS-Report

More information

Exact Algorithms Lecture 7: FPT Hardness and the ETH

Exact Algorithms Lecture 7: FPT Hardness and the ETH Exact Algorithms Lecture 7: FPT Hardness and the ETH February 12, 2016 Lecturer: Michael Lampis 1 Reminder: FPT algorithms Definition 1. A parameterized problem is a function from (χ, k) {0, 1} N to {0,

More information

Let Arguments Go First

Let Arguments Go First Let Arguments Go First Ningning Xie (B) and Bruno C. d. S. Oliveira The University of Hong Kong, Pokfulam, Hong Kong {nnxie,bruno}@cs.hku.hk Abstract. Bi-directional type checking has proved to be an extremely

More information

Dependent Object Types - A foundation for Scala s type system

Dependent 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 information

Induction and Semantics in Dafny

Induction 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

Operational Semantics

Operational 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 information

λ calculus is inconsistent

λ calculus is inconsistent Content Rough timeline COMP 4161 NICTA Advanced Course Advanced Topics in Software Verification Gerwin Klein, June Andronick, Toby Murray λ Intro & motivation, getting started [1] Foundations & Principles

More information

A modern eye on ML type inference

A modern eye on ML type inference 1 Old techniques and recent developments September 2005 2 Types A type is a concise description of the behavior of a program fragment. Typechecking provides safety or security guarantees. It also encourages

More information

GADTs meet Subtyping

GADTs meet Subtyping GADTs meet Subtyping Gabriel Scherer, Didier Rémy Gallium INRIA 2014 Gabriel Scherer, Didier Rémy (Gallium INRIA) GADTs meet Subtyping 2014 1 / 21 A reminder on GADTs GADTs are algebraic data types that

More information

Modal Logic: Implications for Design of a Language for Distributed Computation p.1/53

Modal Logic: Implications for Design of a Language for Distributed Computation p.1/53 Modal Logic: Implications for Design of a Language for Distributed Computation Jonathan Moody (with Frank Pfenning) Department of Computer Science Carnegie Mellon University Modal Logic: Implications for

More information

Girard s System F. Chapter System F. = λ ( f :τ 2 τ 3 ) λ (g:τ 1 τ 2 ) λ (x:τ 1 ) f (g(x)) System F

Girard s System F. Chapter System F. = λ ( f :τ 2 τ 3 ) λ (g:τ 1 τ 2 ) λ (x:τ 1 ) f (g(x)) System F 174 20.1 System F 20.1 System F Chapter 20 Girard s System F The languages we have considered so far are all monomorphic in that every expression has a unique type, given the types of its free variables,

More information

1. 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. 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 information

6.001 Notes: Section 8.1

6.001 Notes: Section 8.1 6.001 Notes: Section 8.1 Slide 8.1.1 In this lecture we are going to introduce a new data type, specifically to deal with symbols. This may sound a bit odd, but if you step back, you may realize that everything

More information

Type Safety. Java and ML are type safe, or strongly typed, languages. C and C++ are often described as weakly typed languages.

Type Safety. Java and ML are type safe, or strongly typed, languages. C and C++ are often described as weakly typed languages. Java and ML are type safe, or strongly typed, languages. CMPSCI 630: Programming Languages Spring 2009 (with thanks to Robert Harper) C and C++ are often described as weakly typed languages. What does

More information

Part III. Chapter 15: Subtyping

Part 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 information

1. Abstract syntax: deep structure and binding. 2. Static semantics: typing rules. 3. Dynamic semantics: execution rules.

1. Abstract syntax: deep structure and binding. 2. Static semantics: typing rules. 3. Dynamic semantics: execution rules. Introduction Formal definitions of programming languages have three parts: CMPSCI 630: Programming Languages Static and Dynamic Semantics Spring 2009 (with thanks to Robert Harper) 1. Abstract syntax:

More information

Symmetry in Type Theory

Symmetry in Type Theory Google May 29th, 2012 What is Symmetry? Definition Symmetry: Two or more things that initially look distinct, may actually be instances of a more general underlying principle. Why do we care? Simplicity.

More information

Supplementary Notes on Abstract Syntax

Supplementary Notes on Abstract Syntax Supplementary Notes on Abstract Syntax 15-312: Foundations of Programming Languages Frank Pfenning Lecture 3 September 3, 2002 Grammars, as we have discussed them so far, define a formal language as a

More information

Lecture Notes on Program Equivalence

Lecture 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 information

Towards efficient, typed LR parsers

Towards efficient, typed LR parsers roduction An automaton An ML implementation Beyond ML Conclusion 1 rançois Pottier and Yann Régis-Gianas June 2005 rançois Pottier and Yann Régis-Gianas roduction An automaton An ML implementation Beyond

More information

Introduction to Homotopy Type Theory

Introduction to Homotopy Type Theory Introduction to Homotopy Type Theory Lecture notes for a course at EWSCS 2017 Thorsten Altenkirch March 5, 2017 1 What is this course about? To explain what Homotopy Type Theory is, I will first talk about

More information

Simplifying and Improving Qualified Types

Simplifying 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 information

A Systematic Approach to Static Access Control

A Systematic Approach to Static Access Control A Systematic Approach to Static Access Control François Pottier INRIA Rocquencourt and Christian Skalka The University of Vermont and Scott Smith The Johns Hopkins University The Java Security Architecture

More information

Formal semantics of loosely typed languages. Joep Verkoelen Vincent Driessen

Formal 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 information

Unification in Maude. Steven Eker

Unification in Maude. Steven Eker Unification in Maude Steven Eker 1 Unification Unification is essentially solving equations in an abstract setting. Given a signature Σ, variables X and terms t 1, t 2 T (Σ) we want to find substitutions

More information

Part III Chapter 15: Subtyping

Part 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 information

Inductive Definitions, continued

Inductive Definitions, continued 1 / 27 Inductive Definitions, continued Assia Mahboubi Jan 7th, 2016 2 / 27 Last lecture Introduction to Coq s inductive types: Introduction, elimination and computation rules; Twofold implementation :

More information

CS-XXX: Graduate Programming Languages. Lecture 17 Recursive Types. Dan Grossman 2012

CS-XXX: Graduate Programming Languages. Lecture 17 Recursive Types. Dan Grossman 2012 CS-XXX: Graduate Programming Languages Lecture 17 Recursive Types Dan Grossman 2012 Where are we System F gave us type abstraction code reuse strong abstractions different from real languages (like ML),

More information

RAISE in Perspective

RAISE in Perspective RAISE in Perspective Klaus Havelund NASA s Jet Propulsion Laboratory, Pasadena, USA Klaus.Havelund@jpl.nasa.gov 1 The Contribution of RAISE The RAISE [6] Specification Language, RSL, originated as a development

More information

Semantics via Syntax. f (4) = if define f (x) =2 x + 55.

Semantics 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 information

Pretty-Big-Step Semantics

Pretty-Big-Step Semantics Pretty-Big-Step Semantics Arthur Charguéraud Inria Saclay Île-de-France & LRI, Université Paris Sud, CNRS arthur.chargueraud@inria.fr Abstract. In spite of the popularity of small-step semantics, big-step

More information

Polymorphic lambda calculus Princ. of Progr. Languages (and Extended ) The University of Birmingham. c Uday Reddy

Polymorphic 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 information

14.1 Encoding for different models of computation

14.1 Encoding for different models of computation Lecture 14 Decidable languages In the previous lecture we discussed some examples of encoding schemes, through which various objects can be represented by strings over a given alphabet. We will begin this

More information

Handout 9: Imperative Programs and State

Handout 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 information

STABILITY AND PARADOX IN ALGORITHMIC LOGIC

STABILITY AND PARADOX IN ALGORITHMIC LOGIC STABILITY AND PARADOX IN ALGORITHMIC LOGIC WAYNE AITKEN, JEFFREY A. BARRETT Abstract. Algorithmic logic is the logic of basic statements concerning algorithms and the algorithmic rules of deduction between

More information

CSCI-GA Scripting Languages

CSCI-GA Scripting Languages CSCI-GA.3033.003 Scripting Languages 12/02/2013 OCaml 1 Acknowledgement The material on these slides is based on notes provided by Dexter Kozen. 2 About OCaml A functional programming language All computation

More information

6.001 Notes: Section 6.1

6.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 information