Type Classes and Instance Chains: A Relational Approach. John Garrett Morris

Size: px
Start display at page:

Download "Type Classes and Instance Chains: A Relational Approach. John Garrett Morris"

Transcription

1 Type Classes and Instance Chains: A Relational Approach by John Garrett Morris A dissertation submitted in partial fulfillment of the requirements for the degree of Doctor of Philosophy in Computer Science Dissertation Committee: Mark P. Jones, Chair Sergio Antoy James G. Hook Andrew P. Tolmach M. Paul Latiolais Portland State University 2013

2 2013 John Garrett Morris

3 i ABSTRACT Type classes, first proposed during the design of the Haskell programming language, extend standard type systems to support overloaded functions. Since their introduction, type classes have been used to address a range of problems, from typing ordering and arithmetic operators to describing heterogeneous lists and limited subtyping. However, while type class programming is useful for a variety of practical problems, its wider use is limited by the inexpressiveness and hidden complexity of current mechanisms. We propose two improvements to existing class systems. First, we introduce several novel language features, instance chains and explicit failure, that increase the expressiveness of type classes while providing more direct expression of current idioms. To validate these features, we have built an implementation of these features, demonstrating their use in a practical setting and their integration with type reconstruction for a Hindley-Milner type system. Second, we define a set-based semantics for type classes that provides a sound basis for reasoning about type class systems, their implementations, and the meanings of programs that use them.

4 ii ACKNOWLEDGMENTS This dissertation, and the research it describes, would not have been possible without the help and support of numerous others over my time as a graduate student. First and foremost, I thank Mark Jones, my advisor, for his advice, encouragement, and for many hours of stimulating and enlightening discussions. Next, I should thank the other members of the HASP research group, and in particular James Hook and Andrew Tolmach, for their feedback and suggestions over the course of this research and development of this dissertation. Finally, I must thank my family for their love and unwavering support, particularly over the past several years.

5 iii TABLE OF CONTENTS Abstract Acknowledgments i ii List of Figures v 1 Introduction Instance Chains and the Habit Class System Outline of Dissertation A Brief Introduction to Polymorphism and Overloading The Hindley-Milner Type System Type Classes The Theory of Qualified Types Extensions of Type Classes Programming with Instance Chains Overlapping Instances in Practice Programming with Type Classes Design of the Habit Class System Case Study: Extensible Data Types Related Work A Logic of Instance Chains Syntax Classes and Implementations Modelling Type Classes Acceptability and Model Existence Entailment and Qualified Types Related Work

6 iv 5 Semantics for Overloading Simply-Typed Lambda Calculus A Simple Semantics for Polymorphism A Simple Semantics for Overloading Example: Polymorphic Identity Functions Related Work The Habit Predicate Solver Entailment and Evidence Simplification Improvement Implementation Mechanisms Related Work Future Work Refining Acceptability Generalizing Superclasses Semantics of Overloading Proof by Cases References

7 v LIST OF FIGURES 3.1 Locations of overlapping instances Numbers of overlapping instances Type-level Peano numerals Type-level insertion sort Type-level greatest common divisor Heterogeneous list types and examples project class and implementation Removing elements of a particular type from an h-list Concrete syntax of Habit predicates, classes, and instances Instance chains and default implementations Extensible expression types First attempt to define expression values Overloaded injection function Overloaded injection function with instance chains Stricter version of injection function Defining expression values Overloaded projection combinator Individual evaluation cases Evaluation functions Expression printers Habit class system syntax (abbreviated) Top-level deduction rules for predicate entailment Axiom-specific deduction rules for predicate entailment Types and terms of the simply typed lambda calculus Typing rules of the simply typed lambda calculus Types and terms of Core ML Typing rules of Core ML

8 vi 5.5 Types and terms of OML Expression typing rules of OML Program typing rule for OML Polymorphic identity function, defined using parametric (id1) and ad hoc (id2) polymorphism Example program definitions Example solver execution (part 1) Example solver execution (part 2) The Node datatype The Tree and Metadata datatypes The Path zipper data type The Trail datatype The SolverState datatype Tactics and associated types Monad instance for the Tactic type constructor Tactic combinators Code size of solver implementation Non-parametric behavior without qualified type

9 1 1. INTRODUCTION Type systems play a central role in assuring program correctness. By providing sound, decidable approximations of semantic properties, types allow compilers to detect entire classes of program errors automatically, and they establish properties of programs and program components, providing a basis for further understanding or verification efforts. However, these benefits come at a cost: limitations in a typing discipline in turn limit the programs that can be well-typed under that discipline. Thus, improving the expressiveness of type systems that is, increasing the fidelity of their approximation of underlying semantic properties is a central concern for the development of typed programming languages, and for program validation as a whole. One early challenge in the development of type systems was to support polymorphism, in which the same symbol or expression can have multiple meanings, corresponding to multiple, distinct types. Following Strachey [62], we identify two classes of polymorphism, parametric and ad hoc. ˆ Parametric polymorphism arises when an expression can take on any of a regularly formed family of types. A typical example of parametric polymorphism is the function that reverses a list. This function can be applied only to list values, and always returns list values. However, assuming a uniform representation of list types, it does not depend upon the type of the elements of the list it could be applied equally well to lists of integers, of Boolean values, or of more complex types. Thus, we can imagine that the reverse

10 2 function should be able to take on any type in the set {[τ] [τ] τ Type}, where Type is the set of all types, and we write [τ] for the type of lists with elements of type τ, and τ τ for the type of functions from values of type τ to values of type τ. This is called parametric because such sets can be captured by writing parameters in types. Thus, instead of the set comprehension above, it is common to write the type of the reverse function as [t] [t], where the type parameter t is implicitly universally quantified. ˆ Ad-hoc polymorphism, also called overloading, arises when an expression s types cannot be described just with types and type variables. For example, we might expect the elem function, which determines whether a candidate value is in a particular list, to be applicable to list of integers or character strings, but not to lists of functions, as we do not expect to have a computable equality test for functions. Similarly, we might expect arithmetic operations, like addition or multiplication, to be applicable to integers and fractional values, but not to character strings. Finally, the implementation of an ad-hoc polymorphic value is likely to be different at each of its types. For example, while we might expect that the reverse function will have uniform implementation for different list element types, we would not expect a common implementation of addition for integers and floating-point values. There have been numerous approaches to strongly-typed parametric polymorphism, including the Hindley-Milner system [5, 21, 41], the Girard-Reynolds polymorphic lambda calculus [15, 52], and, more recently, mechanisms for generics in Java and C#. We will focus on the Hindley-Milner system and its extensions, as it has several advantages for our purposes. First, it has seen relatively wide adoption, underlying the ML and Haskell programming languages and their various dialects. Second, its semantics has been well-studied, providing a basis to

11 3 study the semantics of overloading. Third, expressions in a Hindley-Milner setting have principal, or most general, types. Fourth, the principal type of an expression in a Hindley-Milner setting can be computed from the expression itself, without requiring programmer-supplied type annotation; the process of doing so is called type inference. It is possible to define type inference algorithms in settings that lack principal types; however, because there is no single, most general type for an expression in such a setting, the inferred type of an expression may not correspond to its intended use. The programmer is therefore required either to understand the details of the type inference algorithm, or to defensively add type annotation even when they may not be necessary. By contrast, the ML or Haskell programmer can be confident that the inferred type of an expression is general enough for any well-typed use of the expression. Thus, the existence of principal types is not just an interesting theoretical property, but an important contribution to the usability of languages and tools built on the Hindley-Milner type system. There have been fewer widely-adopted mechanisms for strongly-typed, ad-hoc polymorphism in functional programming languages. Standard ML, for example, provides a syntactic distinction between variables that range over any type and variables that range over any type supporting equality; thus, the elem function could be given a type using the latter kind of variable. However, this mechanism is not generic: it is not extensible to support user-supplied notions of equality, or other sources of ad-hoc polymorphism. Ocaml provides an equality operation that ranges over all types, generating run-time exceptions if it is applied to types such as functions. While general purpose, this lacks the degree of static assurance provided by type-based approaches. One successful approach to strongly-typed ad-hoc polymorphism is provided by type classes, which were originally proposed by Wadler and Blott [70], as an extension of the Hindley-Milner type system. Type classes play three roles in programs: ˆ First, type classes provide a generic mechanism to constrain the instantiation

12 4 of type variables, and thus to provide principal types for expressions with ad-hoc polymorphism. For example, Wadler and Blott describe a type class, named Eq, that contains those types that support equality. This class can be used to constrain the instantiation of variables in the types of polymorphic values. For example, we would infer the type Eq t t [t] Bool for the elem function, where the constraint Eq t indicates that variable t can only be instantiated with types from the Eq class. As we did for parametric polymorphism above, we can interpret this type as a set comprehension, but one in which the domains of variables is limited to the set Eq Type: {τ [τ] Bool τ Eq}. ˆ Second, type classes provide a way to describe the type-specific implementations of ad-hoc polymorphic expressions. For example, we expect the equality function for comparing integers to have a different implementation from the equality operator for character strings. Wadler and Blott observed that these implementation correspond to proofs (that is, the implementations witness the proofs) that Booleans or integers are in the class Eq. This observation has two applications. First, it can help to derive the implementation of overloaded values; for example, we can conclude from the Eq t predicate in its type that, for a given type τ the implementation of elem at type τ [τ] Bool may depend on the proof that τ Eq, that is, on the τ-specific implementation of the equality function. Second, it allows proofs that families of types are in classes. For example, given a witness of τ Eq, we can generically construct a witness that [τ] Eq. These mechanisms admit a good deal of automation. While the programmer must provide the basic proof rules, such as that Int Eq and that τ Eq = [τ] Eq, the compiler can then use them to automatically construct larger proofs, such as to demonstrate that the types [Int] and [[Int]] are also in the Eq class.

13 5 ˆ Third, type classes define properties on types. We have already relied on this interpretation when we wrote set comprehensions such as {τ [τ] Bool τ Eq}, which interpreted classes as subsets of Type, and thus, as properties on Type. When they introduced type classes, Wadler and Blott proposed that some class predicates might apply to multiple types; for example, the predicate Coerce a b would indicate that values of type a could be coerced into values of type b. We can interpret these multi-parameter classes as relations on types; this allows us to begin using classes to capture static information beyond simply the witness of class membership. For example, Jones [31, 32] built on this notion of classes as relations on types to describe mechanisms by which the satisfiability of predicates could be used to improve type inference, both by reducing ambiguity in inferred types and by detecting erroneous programs closer to the original source of the error. Since their introduction, there has been significant interest, both scholarly and practical, in type classes. Unfortunately, this work has frequently uncovered complexities in the class system, and much of it has failed to gain wide acceptance. Wadler and Blott s formal treatment of classes and their implementations [70] provided lexically scoped instances; however, this approach has not been reconciled with principal typing. Haskell compilers have long supported overlapping instances [50], permitting the definition of more generic instances. However, this leads to both complications in reasoning about the type system, and undermines equational approaches to reasoning about the meanings of Haskell expressions. Functional dependencies [32] saw widespread adoption as a tool to combine overloading and type-level reasoning. However, perceived implementation difficulties led to the proposal of new mechanisms, such as indexed type families [56], which separate type classes from other approaches to type-level reasoning. Finally, Haskell implementations differ in their interpretations of these extensions; for example, the Hugs compiler [24] provides a more flexible system of functional

14 6 dependencies than does GHC [14], while GHC s implementation of overlapping instances is more permissive than that of Hugs. Thus, we believe that the design and implementation of type class systems remains an open research problem, of import both to the development of Haskell, and to the development of strongly-typed programming in general. 1.1 INSTANCE CHAINS AND THE HABIT CLASS SYSTEM We have recently been involved in the design of the programming language Habit, a dialect of Haskell intended for high-assurance low-level programming, and particularly in the specification of its type system and implementation of its type inference mechanisms. In doing so, we have developed a new collection of type class features (alternative clauses, exclusion, and backtracking, which we collectively term instance chains), intended to support, and expand upon, the expressive capabilities of Haskell type classes a mechanism both for typing overloaded values and for type-level computation, while providing a sound basis for reasoning about Habit programs, and avoiding the difficulties encountered with Haskell type classes and their extensions. This dissertation describes the results of that effort, in terms of the design of the Habit language, the semantics of classes and of overloaded expressions, and the implementation of a Habit compiler. Language design. The design of the Habit class system is motivated by existing uses of the Haskell class system and its extensions, and by the difficulties and inexpressiveness those uses have encountered. Based on a survey of the literature and of Hackage, an online repository of Haskell libraries and applications, we have identified three significant patterns, beyond simple overloading, in the use of the Haskell class system and its extensions. Each of these patterns has a clearer, or less problematic, expression in the Habit class system than it does in Haskell. We provide a collection of examples to validate these claims and, as a further demonstration

15 7 of the features of the Habit class system, show a new solution to the expression problem. The expression problem is a classic benchmark in programming language expressiveness [2, 37, 53, 69]: it requires the extension of both the constructors of, and the operations over, an abstract data type. Our solution builds on existing Haskell approaches [38, 64] to the expression problem; we improve on those approaches in two respects. First, we support greater flexibility in the injection of values into extensible data types. Second, we provide a generic mechanism to describe operations over extensible data types, whereas existing solutions require the definition of a new type class for each such operation. Semantics of classes. Our semantics of classes provides a sound basis for reasoning about the meaning of classes and class predicates. By providing this semantics, we hope: first, to avoid confusion about the meaning of class system features, as observed in Haskell; second, to provide a foundation for future extensions to the Habit class system; and, third, to provide a standard for implementations of the Habit class system. We begin with an intuitive notion of the meanings of classes, interpreting each class as a mappings from types (or tuples of types) to the corresponding implementations of the class methods We then give a semantics for class predicates by building Kripke frame models [36] from our interpretations of classes. Finally, we define computable notions of acceptability (which describes whether the compiler accepts a given collection of class and instance declarations) and entailment (which describes the proofs the compiler can compute), and we show that each of these notions is sound with respect to our semantics. Semantics of overloading. We build on our semantics of classes to give a semantics of overloaded expressions, completing our semantics of overloading in Habit. We adopt an approach originally developed by Ohori [48] in his semantics of Core ML; unlike other semantics for ML-like languages, Ohori s approach is

16 8 suited to both ad-hoc and parametric polymorphism. We show that our notion of the meanings of classes naturally gives rise to the semantics of their methods, and that the soundness of entailment then gives the soundness of the (simplified) Habit type system with respect to our semantics. Unlike previous semantics of type classes, our approach gives meaning to class methods directly, rather than by translation; we believe this permits more direct reasoning about overloaded values and their meanings. Implementation. It is not enough to be able to reason about overloaded values; we would like to be able to compile them as well. Thus, we conclude by discussing our Habit predicate solver, the implementation of Habit class system in the HASP group s complete Habit compiler. We describe three aspects of the interface between the solver and the type inference component of the Habit compiler: first, the interpretation of entailment proofs as evidence, suitable for compiling overloading; second, the simplification of inferred predicate sets; and third, the computation of type equalities implied by the satisfiability of predicate sets. Finally, we give a broad overview of the data structures and abstractions that make up our solver s implementation and its interface to the remainder of the compiler. 1.2 OUTLINE OF DISSERTATION The primary contributions of this dissertation are: 1. The design of the instance chain mechanisms (alternative clauses, exclusion, and backtracking search) in the Habit class system; 2. A collection of examples, drawn partially from a survey of a large, public repository of Haskell libraries and applications, motivating the design of instance chains, and demonstrating their expressiveness;

17 9 3. A novel semantics of type classes, based on Kripke frame semantics, relating class and instance declarations to intuitive models of classes and their meanings; 4. Validity and entailment relations, describing the interaction between classes and typing, and proofs of their soundness; 5. The first translation-free semantics for programs with overloading, building on Ohori s semantics of Core ML and our semantics of type classes; and, 6. A discussion of our practical implementation of instance chains, and its interactions with type inference, in the context of a prototype compiler for Habit. The remainder of the dissertation proceeds as follows. Related work is summarized at the end of each chapter. Chapter 2 gives a brief introduction to: the Hindley-Milner type system; Wadler and Blott s proposal of type classes; Jones s generalization of type systems with predicates; and, several extensions of type classes implemented by the various Haskell compilers. Chapter 3 describes the language design aspects of our work, including: our survey of type classes in Haskell programs; an intuitive description of the new features of the Habit class system; and, our case study of the expression problem. This chapter addresses contributions (1) and (2). Chapter 4 develops the semantics of classes, and the logic of class predicates, including our development of the validity and entailment relations, and our proofs of the soundness of each. This chapter addresses contributions (3) and (4). Chapter 5 develops the semantics of overloaded expressions; we begin with an introduction to Ohori s approach to semantics and Harrison s [18] extension of that approach to support polymorphic recursion, the continue to describe our semantics of overloading and to prove its soundness. This chapter addresses contribution (5).

18 10 Chapter 6 describes the Habit predicate solver, its interface to the remainder of the Habit compiler, and gives a high-level overview of its implementation. This chapter addresses contribution (6). Finally, chapter 7 sketches several directions for future development of this work.

19 11 2. A BRIEF INTRODUCTION TO POLYMORPHISM AND OVERLOADING In this chapter, we provide a brief introduction to the treatment of polymorphism in typed functional languages, particularly Haskell. Following Strachey [62], we identify two classes of polymorphism: ˆ Parametric polymorphism arises when an expression has regular meanings over its range of types; the name arises from the use of type parameters in describing the types of such value; and, ˆ Ad-hoc polymorphism, or overloading, arises when the meaning of an expression is distinct at different types. We begin by discussing the Hindley-Milner type system ( 2.1), an approach to parametric polymorphism adopted in the programming languages ML, Haskell, and their dialects. We go on to discuss type classes ( 2.2), a feature of Haskell that extends the Hindley-Milner system to accommodate ad-hoc polymorphism. Next, we discuss Jones s theory of qualified types ( 2.3), which generalizes the treatment of type classes to apply to arbitrary predicates on types, and re-establishes many of the advantageous attributes of Hindley-Milner typing. We will rely on Jones s type system in the remainder of the dissertation, allowing us to focus on the class system itself. Finally, we give an overview of several commonly used extensions of Haskell type classes: multi-parameter type classes ( 2.4.1), functional dependences ( 2.4.2), and overlapping instances ( 2.4.3). In particular, we identify a serious flaw in latter ( 2.4.4), setting the stage for the features of the Habit class system that are developed in the remainder of this dissertation.

20 THE HINDLEY-MILNER TYPE SYSTEM The Hindley-Milner type system [5, 21, 41] provides one approach to parametric polymorphism. It assigns type schemes to expressions, capturing generic usage through (implicitly quantified) type variables. For example, the reverse function, which reverses the elements of a list, could be typed as reverse :: [t] [t] meaning that, for any type t, reverse transforms a list with elements from t into another list with elements from t. A polymorphic value can be used at any type that is a generic instance a substitution of types for quantified type variables of its type scheme; in the case of reverse, these include the types [Int] [Int] and [(Int, Bool)] [(Int, Bool)], but not [Int] [Bool]. Intuitively, if Type is the set of all types, then we expect reverse to take on any type in the set {[τ] [τ] τ Type}. This is clearly not the only type scheme that we could assign to reverse; we could also assign it types such as [(a, b)] [(a, b)] or even [Int] [Int]. In this case, it should be apparent that any type scheme we could assign to reverse is (the quantification of) one of the generic instances of the type scheme [a] [a], and thus that [a] [a] is, in some sense, the most general type scheme of the reverse function. Such a type scheme is called a principal type, and is unique (up to renaming of bound variables). A significant feature of Hindley- Milner typing, in contrast to some other systems of parametric polymorphism, is that every expression has a principal type. Further, there is a process, called type inference, that automatically computes the principal type of any well-typed expression. This provides for strong typing with the associated semantic guarantees without requiring programmers to provide explicit type annotations in programs.

21 13 The Hindley-Milner type system, however, provides no support for ad-hoc polymorphism, limiting the expressive power of Hindley-Milner types. For example while the reverse function is fully generic we can expect to apply it to lists of any type the list membership function elem (which determines if a particular value is an element of a list) must be able to compare its arguments for equality, and thus could only be applied to lists whose elements support computable equality comparisons. Thus, while the elem function could have numerous Hindley-Milner types, such as Int [Int] Bool or Char [Char] Bool, it does not have a principal type. A variety of approaches have been used to support ad-hoc polymorphism in Hindley-Milner systems: Standard ML [42], for example, provides distinguished type variables that can only range over types supporting equality, and overloads arithmetic functions to support both the built-in integer and floating point types. However, these mechanisms are not extensible, either to arithmetic operations on user-defined types, such as complex numbers or matrices, or to allow the introduction new overloaded operators, such as ordering comparators. 2.2 TYPE CLASSES Type classes, proposed by Wadler and Blott [70] during the design of the programming language Haskell, provide an extensible mechanism for typing overloaded functions, allowing the definition of both new overloaded operators and new instances of existing overloaded functions. A type class captures an open (i.e., extensible) set of types, associating with each member of the class the implementation of a specific collection of functions, called the class methods. This set is populated by a collection of instance declarations, each describing a particular way of implementing the class methods for a given type or (parametric) range of types. For example, the Eq class, used in Haskell to capture the types that support equality. This class is declared:

22 14 class Eq t where (==) :: t t Bool ( ) :: t t Bool specifying that for a type to be in Eq, it must provide an implementation of equality (==) and inequality ( ) functions. The Haskell standard libraries provide instances of Eq for base types, such as the type of 32-bit integers, like the following: instance Eq Int where x == y = iszero (x - y) x y = not (iszero (x - y)) as well as instances for parameterized types, such as the following instance for pairs: instance (Eq a, Eq b) Eq (a, b) where (x, y) == (x', y') = x == x' && y == y' (x, y) (x', y') = x x' y y' We can characterize the Eq class by identifying those types it includes. Given the instances above, we would expect the Eq class to contain at least the following subset of Type, the set of all types: {Int, (Int, Int), ((Int, Int), Int), (Int, (Int, Int)),... }. We use the Eq class to provide principal types for expressions that depend on equality, such as the elem function in the prior section, introducing type-class predicates that restrict, or qualify, the variables that appear in their types. For example, the type of the equality operator reflects the restriction that it can only be instantiated at types in Eq: (==) :: Eq t t t Bool

23 15 In contrast to the reverse function, which can be used at any generic instance of its type scheme, the (==) function can only be used at generic instances that satisfy its constraints. For example, it can take on types Int Int Bool or but not types such as (Int, Int) (Int, Int) Bool (a b) (a b) Bool, as we do not expect a decidable equality predicate for functions. We can use the overloaded equality operator to define the list membership function: elem x [] = False elem x (y : ys) = x == y elem x ys which would have the principal type scheme elem :: Eq t t [t] Bool including the qualifier, Eq t, arising from the use of (==). Both of these uses of the Eq class are open: the programmer can either add new types to the Eq class, or write new functions that make use of its methods, without having to make any changes to existing code or usage. Wadler and Blott give meaning to overloaded expressions, such as the definition of elem, using a dictionary-passing translation. In this approach, an expression with a qualified type is translated into a function with one (additional) parameter for each predicate in its qualifier. This parameter receives a tuple of type-specific implementations of class methods, called a dictionary, derived from the instance declarations in the program. References to class methods within the expression are translated into references to components of the dictionary arguments, while other overloaded expressions are translated to add suitable dictionary arguments. For

24 16 example, the Eq class has two methods the equality and inequality functions so a dictionary for this class to might be described by tuple of functions of the following type type EqD a = (a a Bool, a a Bool) and each instance declaration would be translated into a corresponding value of type EqD; for example, the instance for integers above would be translated to the following value of type EqD Int: eqintd = (λx y iszero (x - y), λx y not (iszero (x - y))) We can now demonstrate the dictionary-passing translation of the elem function. As shown above, the type scheme of the elem function has one qualifier; therefore, the type scheme of the translated function (for clarity, called elemd) will have one dictionary parameter: elemd :: EqD t t [t] Bool The translation of the body of the elem function is straight-forward: elemd (eq, neq) x [] = False elemd (eq, neq) x (y : ys) = eq x y elemd (eq, neq) x ys Note that the call to (==), a class method, has been transformed into a call to the parameter eq, and that the recursive call to elem has been translated to a call to elemd, with the dictionary argument (eq, neq). We could apply a similar approach to translate instances with qualifiers into dictionary constructors; for example, the instance of Eq for pairs might be translated: eqpaird :: EqD a EqD b EqD (a, b) eqpaird (eqa, neqa) (eqb, neqb) = (eqpair, neqpair) where eqpair (x, y) (x', y') = eqa x x' && eqb y y' neqpair (x, y) (x', y') = neqa x x' neqa y y'

25 17 Finally, where qualifiers can be proved in the original program, dictionary values are inserted in the translated program. For example, we would not expect a use of elem on list of integers to have a qualified type, as the constraint Eq Int can be discharged: fiveisodd :: Bool fiveisodd = elem 5 [1,3..] In the translation of this code, elemd still needs dictionary arguments; however, we can provide those arguments using the dictionaries built from the instance declarations in the source program: fiveisoddd :: Bool fiveisoddd = elemd eqintd 5 [1,3..] The version we have presented here follows Wadler and Blott s description of type classes. To formalize type classes, they present a typing and translation relation in which classes and instances are lexically scoped, instead of being toplevel, global declarations. This introduces some formal difficulties not present in their more intuitive description; in particular, as they observe, the introduction of local instances undermines principal typing. 2.3 THE THEORY OF QUALIFIED TYPES In his theory of qualified types [28], Jones develops a general system of typing with qualification. Rather than focus on a particular form of predicate, as Wadler and Blott did in their work on type classes, Jones adopts an abstract notion of predicate. He demonstrates that his system can describe not only typing with type classes, but also forms of record typing and subsumption. He presents a generic overloaded lambda calculus, called OML, and its type system; because he treats predicates abstractly, Jones s type system distinguishes the generic manipulation

26 18 of predicates necessary for typing from the domain-specific entailment relation among predicates. Jones gives a notion of principal typing for OML; this is made more complex by the presence of predicates in types. We have previously described a principal type scheme for a given expression as being one such that any other type of the expression is a generic instance of its principal type, and we have claimed that the principal type is unique, up to renaming of bound variables. For example, we could give the reverse function either of the type schemes [a] [a] or [b] [b]; however, while these types are syntactically distinct, we can transform either to match the other, by suitable substitution for the bound variables a and b. This is no longer true for qualified types. For example, with the instances in the Haskell standard libraries, the predicate Eq [t] holds if, and only if, the predicate Eq t also holds. Thus, we can observe that, in an intuitive sense, the two type schemes Eq t t t and Eq [u] u u describe the same sets of types; however, there is no transformation of the variables t and u such that one will equal the other. To account for this difficulty, Jones develops the notion of a principal satisfiable type [28]. Intuitively, given some initial predicates P 0, a principal satisfiable type P τ of some expression is one such that, for any other type Q τ of the same expression, τ is a generic instance of τ, and, if Q follows from P 0, the instantiation of P also follows from P 0. Jones shows that each OML expression has a principal satisfiable type, and gives a type inference algorithm that computes such a type scheme for any well-typed OML expression. Jones also develops a translation-based semantics for overloaded expressions, generalizing the approach of Wadler and Blott. As he treats predicates abstractly, he also introduces a notion of evidence, an abstraction of the implementation of predicates. Different forms of predicates give rise to different forms of evidence; for example, type classes might use dictionaries as evidence, as in the Wadler and Blott system, while evidence for record predicates might correspond to offsets

27 19 into underlying data structures. As his type system is independent of the form of predicates, so his translation is independent of the form of evidence. His semantics is based on a translation to a typed lambda calculus with explicit introduction and elimination of evidence values, and a version of the entailment relation annotated to compute evidence. One consequence of any instantiation of Jones s system of qualified types, including type classes, is that part of the semantics of programs is determined automatically by the compiler, based solely on the typing derivations of expressions. We would hope that, just as each of an expression s principal qualified types describes the same collection of types, each distinct translation of the expression has the same meaning. Jones refers to this property as the coherence of the translation. In some cases, we cannot hope to have a coherent translation. For example, the Haskell report defines classes Show and Read for converting values to and from textual representations, including class methods with the types show :: Show t t String read :: Read t String t Given these functions, the expression show read has type (Show t, Read t) String String where the type parameter t in the Show and Read predicates does not appear in the type of the expression. Such types are called ambiguous, as, in the translation of an expression with an ambiguous type, the choice of dictionaries is necessarily arbitrary. Jones shows that, assuming a constraint on the entailment relation he calls uniqueness of evidence, the translations of expressions with unambiguous types in his semantics are coherent. Jones s system is a natural foundation for our work on type classes: it allows us to focus on the class predicates and their manipulation, without having to simultaneously address the concerns of typing and type inference. His approach makes

28 20 some assumptions of the entailment relation, such as uniqueness of evidence; we shall thus have to demonstrate that our entailment relation meets those assumptions. We will give a more formal recounting of the types and terms of OML when we discuss the semantics of overloading in Chapter 5; while we assume his type system, our semantics is not based on translation. 2.4 EXTENSIONS OF TYPE CLASSES We conclude this background material by discussing several commonly used extensions to the Haskell class system: multi-parameter type classes, functional dependencies, and overlapping instances. We have two purposes in doing so. First, multi-parameter type classes and functional dependencies are both central to the Habit class system, and will appear regularly in the remainder of the dissertation. Second, the discussion of functional dependencies and overlapping instances will demonstrate applications of the notions of principal satisfiable types and coherence, described in the previous section Multi-Parameter Type Classes Although Wadler and Blott [70] focussed on type classes with a single parameter (corresponding to sets of types with associated operators), they proposed that type classes could also apply to more than one parameter. They gave the example of a class to capture valid coercions between types; for example: class Coerce a b where coerce :: a b instance Coerce Int Float where coerce = fromintegral instance Coerce a b Coerce [a] [b] where coerce = map coerce

29 21 Just as single-parameter type classes can be interpreted as sets of types, multiparameter type classes can be interpreted as relations on types (i.e., sets of tuples of types). From the instances above, we would expect Coerce to include the following subset of Type Type { Int, Float, [Int], [Float],... }, where we write type tuples with angle brackets to distinguish them from the tuple type constructor Functional Dependencies Despite their conceptual simplicity, many anticipated uses of multi-parameter type classes were problematic. For example [32], we might hope to use a type class to capture the relationship between collection types c and their element types e: class Elems c e where empty :: c insert :: e c c elem :: e c Bool (A fully-featured collections class might have many more methods; however, these are sufficient for our purposes.) This class might be populated for lists: instance Eq t Elems [t] t where... and could similarly be populated for binary search trees: instance Ord t Elems (BTree t) t where... Binary search trees need an ordering on their key type; in this case, that requirement is captured by the Ord qualification, which provides an (overloaded) (<) operator. Unfortunately, any attempt to use this class will be problematic. One problem can be observed in the type of the empty method:

30 22 empty :: Elems c e c The type of empty is ambiguous: any attempt to discharge this predicate would require an arbitrary choice by the compiler as to the instantiation of e, and thus the evidence for the predicate Elems c e. As expressions containing empty cannot have a coherent translation, the compiler will reject its definition. A further problem can be demonstrated with the insert function. Using it, we could write the following function insert2 c = insert True (insert 'x' c) to insert both the Boolean constant True and the character constant 'x' into the collection c. This function has the type: insert2 :: (Elems c Bool, Elems c Char) c c Neither our examples of lists nor binary trees support this kind of usage. We will describe a well-typed heterogenous collection later ( 3.2.2); however, its types would not fit the pattern required by the Elems class. Thus, while not erroneous given the current definitions, this constraint is likely to be unsatisfiable. Both of these problems might be resolved if we restricted the Elems class to homogeneous collections. We could then observe that the type of empty is not truly ambiguous, as the type of the collection is specified and thus the type of elements is determined, and that insert2 is an error, as it would require a collection type with distinct element types, an unsatisfiable constraint. To restrict the Elems class to homogeneous collections, we must require that, for any type τ, there be at most one type τ such that the predicate Elems τ τ holds. This is an example of a functional dependency [40]. Functional dependencies are properties of a relation; the Elem class as populated by the prior instance has such a dependency. However, as Haskell type classes are open, we cannot be sure that future instances will preserve the dependency. Jones proposed adding functional dependency constraints to classes, such that all instances of that class

31 23 were required to maintain certain dependencies [32]. For example, we could add a functional dependency constraint to the Elems class: class Elems c e c e This constraint plays two roles. First, it requires that all instances of the Elems class maintain the functional dependency. For example, given the instances earlier, it would be an error to add an instance such as the following instance Elems [Int] Char where... as there would be two element types (Int and Char) associated with the collection type [Int]. Second, it provides additional information about the satisfiability of Elems constraints, addressing the concerns with the earlier uses of the Elems class. In the case of empty, it allows the compiler to conclude that, for any type c, there is at most one type such that Elems c e is satisfiable, with one evidence value for Elems c e, and thus that the type of empty, Elems c e c is not truly ambiguous. In the case of insert2, it allows the compiler to determine that the constraints Elems c Bool and Elems c Char could only be satisfied if Bool and Char where the same type; instead, because they are distinct, the compiler rejects this definition Overlapping Instances Two instances overlap if they could apply to the same predicate. For example, consider a type class C with the following instances: instance C (a, [b]) where... instance C ([a], b) where... These instances overlap: either could be used to solve predicates like C ([Int], [Int]). However, the compiler has no guarantee that the class methods are implemented

32 24 equivalently for both instances that is, there is no guarantee that the evidence for C ([Int], [Int]) is unique and so a program with both instances may have multiple, distinct interpretations. To avoid this kind of (potential) incoherence, Haskell 98 prohibits any overlap between instances. This restriction is sometimes inconvenient. For one example, the Show class in the Haskell standard libraries includes types whose values have a textual representation: class Show t where show :: t String... Conventionally, show generates the Haskell syntax for its argument. For example, Haskell s syntax for lists surrounds the elements with brackets and separates them with commas. We could write a Show instance for lists that used this syntax: instance Show t Show [t] where show xs = "[" ++ intercalate "," (map show xs) ++ "]" In addition to its standard syntax for lists, Haskell has special syntax to allow lists of characters to be written as character strings, delimited by double quotes. We might like to add a special instance of Show to handle this case, as in this simplified example: instance Show [Char] where show xs = "\"" ++ xs ++ "\"" These two instances overlap: a [Char] value could be rendered either as a list or as a string. As a result, a program containing both instances would be rejected by a Haskell compiler. Popular Haskell compilers have long supported language extensions that allows overlapping instances, as long as the instances can be ordered by specificity [26, 50].

33 25 This extension attempts to allow programmers to provide both general and typespecific instances, such as in the Show example above. We can specify this extension as follows. Given two instances for some class D: instance P1 D τ i where... instance P2 D υ i where... these instances overlap if there is some instantiation of the variables in the τ i such that the equal an instantiation of the variables in the υ i. The first instance is more specific than the second if the τ i can be instantiated to match the υ i, but not vice versa. In the example instances of C given at the start of the section, both instances overlap, but neither is more specific than the other. Both are more specific than the instance instance C (a, b) where... and less specific than the instance instance C ([a], [b]) where... In resolving any individual predicate, the compiler chooses the most specific instance such that the instance conclusion unifies with the goal predicate. Note that the contexts (P1 and P2 above) do not factor into this determination; if the most specific instance does not solve the predicate, the compiler does not attempt to use less specific instances. While the overlapping instances extension has a long history of use in the Haskell community, it is (despite the prior paragraphs) still mostly unspecified. This has two effects. First, different compilers implement the extension differently. For example, Hugs requires that any pair of overlapping instances be orderable by specificity; in contrast, GHC only requires that overlapping instances be orderable at predicates used in the program. Thus, GHC would accept a set of instances like instance C (a, b) where...

34 26 instance C ([a], b) where... instance C (a, [b]) where... and only indicate an error if the programmer used a predicate of the form C ([t], [u]). Hugs, on the other hand, would reject the program because of the overlap between the second two instances, regardless of the predicates that appeared in the remainder of the program. Second, the interaction of the overlapping instances extension with other class system features is unspecified, or unsupported. For instance, the Haskell report specifies a simplification process, called context reduction, that attempts to reduce the complexity of inferred predicates [49, 4.5.3]. Given the instance of Show for lists above, for example, context reduction would simplify the predicate Show [t] to Show t. However, in the presence of overlapping instances, this simplification may not be sound, as there can be instances of Show [t] that do not correspond to instances of Show t. For another example, Hugs does not take the overlapping instances extension into account when validating instances against functional dependency constraints. While GHC continues to support overlapping instances, it does not support overlap in indexed type families (a feature for type-level programming), as such overlaps could introduce soundness issues The Coherence Problem Despite their practical utility, we argue that, to be useful, overlapping instances must rely on an incoherent translation; this reliance, in turn, can be used to generate apparently nonsensical behavior. Thus, we believe that even if the problems of specification mentioned in the previous section could be resolved, overlapping instances would remain problematic in Haskell, or Haskell-like languages. Suppose that we had a class with a generic instance, such as the following. module A where

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

Haskell 98 in short! CPSC 449 Principles of Programming Languages

Haskell 98 in short! CPSC 449 Principles of Programming Languages Haskell 98 in short! n Syntax and type inferencing similar to ML! n Strongly typed! n Allows for pattern matching in definitions! n Uses lazy evaluation" F definition of infinite lists possible! n Has

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

Overloading, Type Classes, and Algebraic Datatypes

Overloading, 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 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

Type Processing by Constraint Reasoning

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

The design of a programming language for provably correct programs: success and failure

The design of a programming language for provably correct programs: success and failure The design of a programming language for provably correct programs: success and failure Don Sannella Laboratory for Foundations of Computer Science School of Informatics, University of Edinburgh http://homepages.inf.ed.ac.uk/dts

More information

Advances in Programming Languages

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

Types and Type Inference

Types and Type Inference CS 242 2012 Types and Type Inference Notes modified from John Mitchell and Kathleen Fisher Reading: Concepts in Programming Languages, Revised Chapter 6 - handout on Web!! Outline General discussion of

More information

Introduction. chapter Functions

Introduction. chapter Functions chapter 1 Introduction In this chapter we set the stage for the rest of the book. We start by reviewing the notion of a function, then introduce the concept of functional programming, summarise the main

More information

Introduction to Programming, Aug-Dec 2006

Introduction to Programming, Aug-Dec 2006 Introduction to Programming, Aug-Dec 2006 Lecture 3, Friday 11 Aug 2006 Lists... We can implicitly decompose a list into its head and tail by providing a pattern with two variables to denote the two components

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

Types and Type Inference

Types and Type Inference Types and Type Inference Mooly Sagiv Slides by Kathleen Fisher and John Mitchell Reading: Concepts in Programming Languages, Revised Chapter 6 - handout on the course homepage Outline General discussion

More information

Haskell Introduction Lists Other Structures Data Structures. Haskell Introduction. Mark Snyder

Haskell Introduction Lists Other Structures Data Structures. Haskell Introduction. Mark Snyder Outline 1 2 3 4 What is Haskell? Haskell is a functional programming language. Characteristics functional non-strict ( lazy ) pure (no side effects*) strongly statically typed available compiled and interpreted

More information

Second-Order Type Systems

Second-Order Type Systems #1 Second-Order Type Systems Homework 5 Summary Student : 37.9704 Student : 44.4466 ORIGINAL : 50.2442 Student : 50.8275 Student : 50.8633 Student : 50.9181 Student : 52.1347 Student : 52.1633 Student

More information

Course year Typeclasses and their instances

Course year Typeclasses and their instances Course year 2016-2017 Typeclasses and their instances Doaitse Swierstra and Atze Dijkstra with extra s Utrecht University September 29, 2016 1. The basics 2 Overloading versus parametric polymorphism 1

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

CS558 Programming Languages

CS558 Programming Languages CS558 Programming Languages Winter 2018 Lecture 7b Andrew Tolmach Portland State University 1994-2018 Dynamic Type Checking Static type checking offers the great advantage of catching errors early And

More information

Type Systems, Type Inference, and Polymorphism

Type Systems, Type Inference, and Polymorphism 6 Type Systems, Type Inference, and Polymorphism Programming involves a wide range of computational constructs, such as data structures, functions, objects, communication channels, and threads of control.

More information

User-Defined Algebraic Data Types

User-Defined Algebraic Data Types 72 Static Semantics User-Defined Types User-Defined Algebraic Data Types An algebraic data type declaration has the general form: data cx T α 1... α k = K 1 τ 11... τ 1k1... K n τ n1... τ nkn introduces

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

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

Type Systems. Pierce Ch. 3, 8, 11, 15 CSE

Type Systems. Pierce Ch. 3, 8, 11, 15 CSE Type Systems Pierce Ch. 3, 8, 11, 15 CSE 6341 1 A Simple Language ::= true false if then else 0 succ pred iszero Simple untyped expressions Natural numbers encoded as succ succ

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

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

Programming Language Concepts: Lecture 19

Programming Language Concepts: Lecture 19 Programming Language Concepts: Lecture 19 Madhavan Mukund Chennai Mathematical Institute madhavan@cmi.ac.in http://www.cmi.ac.in/~madhavan/courses/pl2009 PLC 2009, Lecture 19, 01 April 2009 Adding types

More information

3.4 Deduction and Evaluation: Tools Conditional-Equational Logic

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

Variations on Variants

Variations on Variants Variations on Variants J. Garrett Morris The University of Edinburgh Edinburgh, UK Garrett.Morris@ed.ac.uk Abstract Extensible variants improve the modularity and expressiveness of programming languages:

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

A system of constructor classes: overloading and implicit higher-order polymorphism

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

Data Types. Every program uses data, either explicitly or implicitly to arrive at a result.

Data Types. Every program uses data, either explicitly or implicitly to arrive at a result. Every program uses data, either explicitly or implicitly to arrive at a result. Data in a program is collected into data structures, and is manipulated by algorithms. Algorithms + Data Structures = Programs

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

Programming in Omega Part 1. Tim Sheard Portland State University

Programming in Omega Part 1. Tim Sheard Portland State University Programming in Omega Part 1 Tim Sheard Portland State University Tim Sheard Computer Science Department Portland State University Portland, Oregon PSU PL Research at Portland State University The Programming

More information

Recursive Types and Subtyping

Recursive Types and Subtyping Recursive Types and Subtyping #1 One-Slide Summary Recursive types (e.g., list) make the typed lambda calculus as powerful as the untyped lambda calculus. If is a subtype of then any expression of type

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

Coq with Classes. Matthieu Sozeau. Journées PPS 2011 September 5th 2011 Trouville, France. Project Team πr 2 INRIA Paris

Coq with Classes. Matthieu Sozeau. Journées PPS 2011 September 5th 2011 Trouville, France. Project Team πr 2 INRIA Paris Coq with Classes Matthieu Sozeau Project Team πr 2 INRIA Paris Journées PPS 2011 September 5th 2011 Trouville, France This talk A quick overview of Coq Elaboration Type Classes Matthieu Sozeau - Coq with

More information

CSci 450: Org. of Programming Languages Overloading and Type Classes

CSci 450: Org. of Programming Languages Overloading and Type Classes CSci 450: Org. of Programming Languages Overloading and Type Classes H. Conrad Cunningham 27 October 2017 (after class) Contents 9 Overloading and Type Classes 1 9.1 Chapter Introduction.........................

More information

CS558 Programming Languages

CS558 Programming Languages CS558 Programming Languages Fall 2017 Lecture 7b Andrew Tolmach Portland State University 1994-2017 Type Inference Some statically typed languages, like ML (and to a lesser extent Scala), offer alternative

More information

RSL Reference Manual

RSL Reference Manual RSL Reference Manual Part No.: Date: April 6, 1990 Original Authors: Klaus Havelund, Anne Haxthausen Copyright c 1990 Computer Resources International A/S This document is issued on a restricted basis

More information

Functional Logic Programming Language Curry

Functional Logic Programming Language Curry Functional Logic Programming Language Curry Xiang Yin Department of Computer Science McMaster University November 9, 2010 Outline Functional Logic Programming Language 1 Functional Logic Programming Language

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

CSC312 Principles of Programming Languages : Functional Programming Language. Copyright 2006 The McGraw-Hill Companies, Inc.

CSC312 Principles of Programming Languages : Functional Programming Language. Copyright 2006 The McGraw-Hill Companies, Inc. CSC312 Principles of Programming Languages : Functional Programming Language Overview of Functional Languages They emerged in the 1960 s with Lisp Functional programming mirrors mathematical functions:

More information

Functional Programming. Big Picture. Design of Programming Languages

Functional Programming. Big Picture. Design of Programming Languages Functional Programming Big Picture What we ve learned so far: Imperative Programming Languages Variables, binding, scoping, reference environment, etc What s next: Functional Programming Languages Semantics

More information

Type Systems COMP 311 Rice University Houston, Texas

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

Types, Type Inference and Unification

Types, Type Inference and Unification Types, Type Inference and Unification Mooly Sagiv Slides by Kathleen Fisher and John Mitchell Cornell CS 6110 Summary (Functional Programming) Lambda Calculus Basic ML Advanced ML: Modules, References,

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

Once Upon a Polymorphic Type

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

An Evolution of Mathematical Tools

An Evolution of Mathematical Tools An Evolution of Mathematical Tools From Conceptualization to Formalization Here's what we do when we build a formal model (or do a computation): 0. Identify a collection of objects/events in the real world.

More information

Lambda calculus. Wouter Swierstra and Alejandro Serrano. Advanced functional programming - Lecture 6

Lambda calculus. Wouter Swierstra and Alejandro Serrano. Advanced functional programming - Lecture 6 Lambda calculus Advanced functional programming - Lecture 6 Wouter Swierstra and Alejandro Serrano 1 Today Lambda calculus the foundation of functional programming What makes lambda calculus such a universal

More information

Simon Peyton Jones Microsoft Research August 2013

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

Typed Scheme: Scheme with Static Types

Typed Scheme: Scheme with Static Types Typed Scheme: Scheme with Static Types Version 4.1.1 Sam Tobin-Hochstadt October 5, 2008 Typed Scheme is a Scheme-like language, with a type system that supports common Scheme programming idioms. Explicit

More information

Type Checking and Type Equality

Type Checking and Type Equality Type Checking and Type Equality Type systems are the biggest point of variation across programming languages. Even languages that look similar are often greatly different when it comes to their type systems.

More information

n n Try tutorial on front page to get started! n spring13/ n Stack Overflow!

n   n Try tutorial on front page to get started! n   spring13/ n Stack Overflow! Announcements n Rainbow grades: HW1-6, Quiz1-5, Exam1 n Still grading: HW7, Quiz6, Exam2 Intro to Haskell n HW8 due today n HW9, Haskell, out tonight, due Nov. 16 th n Individual assignment n Start early!

More information

Cover Page. The handle holds various files of this Leiden University dissertation

Cover Page. The handle   holds various files of this Leiden University dissertation Cover Page The handle http://hdl.handle.net/1887/22891 holds various files of this Leiden University dissertation Author: Gouw, Stijn de Title: Combining monitoring with run-time assertion checking Issue

More information

IA014: Advanced Functional Programming

IA014: Advanced Functional Programming IA014: Advanced Functional Programming 8. GADT Generalized Algebraic Data Types (and type extensions) Jan Obdržálek obdrzalek@fi.muni.cz Faculty of Informatics, Masaryk University, Brno Motivation IA014

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

COMP 181. Agenda. Midterm topics. Today: type checking. Purpose of types. Type errors. Type checking

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

CS 565: Programming Languages. Spring 2008 Tu, Th: 16:30-17:45 Room LWSN 1106

CS 565: Programming Languages. Spring 2008 Tu, Th: 16:30-17:45 Room LWSN 1106 CS 565: Programming Languages Spring 2008 Tu, Th: 16:30-17:45 Room LWSN 1106 Administrivia Who am I? Course web page http://www.cs.purdue.edu/homes/peugster/cs565spring08/ Office hours By appointment Main

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

Structural polymorphism in Generic Haskell

Structural polymorphism in Generic Haskell Structural polymorphism in Generic Haskell Andres Löh andres@cs.uu.nl 5 February 2005 Overview About Haskell Genericity and other types of polymorphism Examples of generic functions Generic Haskell Overview

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

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/ October 13, 2004 Lambda Calculus and Type

More information

CS 11 Haskell track: lecture 1

CS 11 Haskell track: lecture 1 CS 11 Haskell track: lecture 1 This week: Introduction/motivation/pep talk Basics of Haskell Prerequisite Knowledge of basic functional programming e.g. Scheme, Ocaml, Erlang CS 1, CS 4 "permission of

More information

CS558 Programming Languages

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

7. Introduction to Denotational Semantics. Oscar Nierstrasz

7. Introduction to Denotational Semantics. Oscar Nierstrasz 7. Introduction to Denotational Semantics Oscar Nierstrasz Roadmap > Syntax and Semantics > Semantics of Expressions > Semantics of Assignment > Other Issues References > D. A. Schmidt, Denotational Semantics,

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

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

Recursion and Induction: Haskell; Primitive Data Types; Writing Function Definitions

Recursion and Induction: Haskell; Primitive Data Types; Writing Function Definitions Recursion and Induction: Haskell; Primitive Data Types; Writing Function Definitions Greg Plaxton Theory in Programming Practice, Spring 2005 Department of Computer Science University of Texas at Austin

More information

To What Extend Is Type Inference for Parameteric Polymorphism Possible in the Presence of Ad-Hoc and Subtype Polymorphism

To What Extend Is Type Inference for Parameteric Polymorphism Possible in the Presence of Ad-Hoc and Subtype Polymorphism To What Extend Is Type Inference for Parameteric Polymorphism Possible in the Presence of Ad-Hoc and Subtype Polymorphism Daniel Marty University of Applied Sciences Rapperswil Supervised by Prof. Dr.

More information

Polymorphism and Type Inference

Polymorphism and Type Inference Polymorphism and Type Inference Volker Stolz stolz@ifi.uio.no Department of Informatics University of Oslo Initially by Gerardo Schneider. Based on John C. Mitchell s slides (Stanford U.) Compile-time

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

First-Class Type Classes

First-Class Type Classes First-Class Type Classes Matthieu Sozeau Joint work with Nicolas Oury LRI, Univ. Paris-Sud - Démons Team & INRIA Saclay - ProVal Project Gallium Seminar November 3rd 2008 INRIA Rocquencourt Solutions for

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

Haskell Overview II (2A) Young Won Lim 8/9/16

Haskell Overview II (2A) Young Won Lim 8/9/16 (2A) Copyright (c) 2016 Young W. Lim. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published

More information

Basic Foundations of Isabelle/HOL

Basic Foundations of Isabelle/HOL Basic Foundations of Isabelle/HOL Peter Wullinger May 16th 2007 1 / 29 1 Introduction into Isabelle s HOL Why Type Theory Basic Type Syntax 2 More HOL Typed λ Calculus HOL Rules 3 Example proof 2 / 29

More information

Qualified Types for MLF

Qualified Types for MLF Qualified Types for MLF Daan Leijen Andres Löh Institute of Information and Computing Sciences, Utrecht University PO Box 80089, 3508 TB Utrecht, The Netherlands {daan,andres}@csuunl Abstract MLF is a

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

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

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

Chapter 11 :: Functional Languages

Chapter 11 :: Functional Languages Chapter 11 :: Functional Languages Programming Language Pragmatics Michael L. Scott Copyright 2016 Elsevier 1 Chapter11_Functional_Languages_4e - Tue November 21, 2017 Historical Origins The imperative

More information

The Design of Core C++ (Notes)

The Design of Core C++ (Notes) The Design of Core C++ (Notes) Uday Reddy May 13, 1994 This note is to define a small formal language called Core C++ which reflects the essential structure of C++. As the name implies, the design only

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

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

Chapter 1. Introduction

Chapter 1. Introduction 1 Chapter 1 Introduction An exciting development of the 21st century is that the 20th-century vision of mechanized program verification is finally becoming practical, thanks to 30 years of advances in

More information

SOFTWARE ENGINEERING DESIGN I

SOFTWARE 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 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

Recursive Types and Subtyping

Recursive Types and Subtyping Recursive Types and Subtyping #1 One-Slide Summary Recall: Recursive types (e.g., τ list) make the typed lambda calculus as powerful as the untyped lambda calculus. If τ is a subtype of σ then any expression

More information

Part I Logic programming paradigm

Part I Logic programming paradigm Part I Logic programming paradigm 1 Logic programming and pure Prolog 1.1 Introduction 3 1.2 Syntax 4 1.3 The meaning of a program 7 1.4 Computing with equations 9 1.5 Prolog: the first steps 15 1.6 Two

More information

DETECTING NON-TERMINATION IN CONSTRAINT HANDLING RULES

DETECTING NON-TERMINATION IN CONSTRAINT HANDLING RULES DETECTING NON-TERMINATION IN CONSTRAINT HANDLING RULES DETECTING NON-TERMINATION IN CONSTRAINT HANDLING RULES By ERSHAD RAHIMIKIA, B.SOFTWARE ENGINEERING A Thesis Submitted to the School of Graduate Studies

More information

CS 457/557: Functional Languages

CS 457/557: Functional Languages CS 457/557: Functional Languages From Trees to Type Classes Mark P Jones Portland State University 1 Trees:! " There are many kinds of tree data structure.! " For example: data BinTree a = Leaf a BinTree

More information

CPS 506 Comparative Programming Languages. Programming Language Paradigm

CPS 506 Comparative Programming Languages. Programming Language Paradigm CPS 506 Comparative Programming Languages Functional Programming Language Paradigm Topics Introduction Mathematical Functions Fundamentals of Functional Programming Languages The First Functional Programming

More information

Type Classes in Haskell Tom Schrijvers. Leuven Haskell User Group

Type Classes in Haskell Tom Schrijvers. Leuven Haskell User Group Type Classes in Haskell Tom Schrijvers Leuven Haskell User Group Haskell Research Team Partners Monads Type Classes GHC Folds Pattern Matching Equational Reasoning DSLs Advanced Types Adhoc Overloading

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

Lecture Overview. [Scott, chapter 7] [Sebesta, chapter 6]

Lecture Overview. [Scott, chapter 7] [Sebesta, chapter 6] 1 Lecture Overview Types 1. Type systems 2. How to think about types 3. The classification of types 4. Type equivalence structural equivalence name equivalence 5. Type compatibility 6. Type inference [Scott,

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

Reasoning About Set Comprehensions

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

Introduction to System F. Lecture 18 CS 565 4/20/09

Introduction to System F. Lecture 18 CS 565 4/20/09 Introduction to System F Lecture 18 CS 565 4/20/09 The Limitations of F 1 (simply-typed λ- calculus) In F 1 each function works exactly for one type Example: the identity function id = λx:τ. x : τ τ We

More information

Type Checking. Outline. General properties of type systems. Types in programming languages. Notation for type rules.

Type Checking. Outline. General properties of type systems. Types in programming languages. Notation for type rules. Outline Type Checking General properties of type systems Types in programming languages Notation for type rules Logical rules of inference Common type rules 2 Static Checking Refers to the compile-time

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