Advanced Functional Programming

Similar documents
Type Classes with Functional Dependencies

Programming Language Rankings. Lecture 15: Type Inference, polymorphism & Type Classes. Top Combined. Tiobe Index. CSC 131! Fall, 2014!

POLYTYPIC PROGRAMMING OR: Programming Language Theory is Helpful

Aspect-Oriented Programming with Type Classes

Regular Expressions and Automata using Haskell

First Class Overloading via Insersection Type Parameters

Idris, a General Purpose Dependently Typed Programming Language: Design and Implementation

Adding GADTs to OCaml the direct approach

CSCI 253. Object Oriented Programming (OOP) Overview. George Blankenship 1. Object Oriented Design: Java Review OOP George Blankenship.

Programming Fundamentals. Lesson 20 Sections

Poor Man's Type Classes

Lecture 12: Abstract data types

Deterministic Discrete Modeling

Formal Engineering for Industrial Software Development

Operator Overloading. Lecture 8. Operator Overloading. Running Example: Complex Numbers. Syntax. What can be overloaded. Syntax -- First Example

Static vs. Dynamic. Lecture 10: Static Semantics Overview 1. Typical Semantic Errors: Java, C++ Typical Tasks of the Semantic Analyzer

Checking Access to Protected Members in the Java Virtual Machine

Java Interview Questions and Answers

Glossary of Object Oriented Terms

OutsideIn(X) Modular type inference with local assumptions

Programming and Reasoning with Algebraic Effects and Dependent Types

The Clean programming language. Group 25, Jingui Li, Daren Tuzi

Advanced Functional Programming (9) Domain Specific Embedded Languages

The Constrained-Monad Problem

Fun with Phantom Types

Object-Oriented Design Lecture 4 CSU 370 Fall 2007 (Pucella) Tuesday, Sep 18, 2007

Practical Generic Programming with OCaml

Introducing Formal Methods. Software Engineering and Formal Methods

Python 2 and 3 compatibility testing via optional run-time type checking

Functional Programming. Functional Programming Languages. Chapter 14. Introduction

CS-XXX: Graduate Programming Languages. Lecture 25 Multiple Inheritance and Interfaces. Dan Grossman 2012

Storage Classes CS 110B - Rule Storage Classes Page 18-1 \handouts\storclas

Class 16: Function Parameters and Polymorphism

How To Write A Generic Program In Hf (For All People)

The Needle Programming Language

Gluing things together with Haskell. Neil Mitchell

This session. Abstract Data Types. Modularisation. Naming modules. Functional Programming and Reasoning

Moving from CS 61A Scheme to CS 61B Java

Functional Programming

Chapter 7: Functional Programming Languages

Timber: A Programming Language for Real-Time Embedded Systems

1 bool operator==(complex a, Complex b) { 2 return a.real()==b.real() 3 && a.imag()==b.imag(); 4 } 1 bool Complex::operator==(Complex b) {

3 Pillars of Object-oriented Programming. Industrial Programming Systems Programming & Scripting. Extending the Example.

Lecture Data Types and Types of a Language

Sources: On the Web: Slides will be available on:

Detecting Pattern-Match Failures in Haskell. Neil Mitchell and Colin Runciman York University

11 November

Cross-platform Compilers for Functional Languages

Embedding effect systems in Haskell

On Understanding Types, Data Abstraction, and Polymorphism

The Relational Model. Why Study the Relational Model? Relational Database: Definitions. Chapter 3

Parametric Domain-theoretic models of Linear Abadi & Plotkin Logic

On Understanding Types, Data Abstraction, and Polymorphism

Anatomy of Programming Languages. William R. Cook

Java Interfaces. Recall: A List Interface. Another Java Interface Example. Interface Notes. Why an interface construct? Interfaces & Java Types

Journal of Functional Programming, volume 3 number 4, Dynamics in ML

SE 360 Advances in Software Development Object Oriented Development in Java. Polymorphism. Dr. Senem Kumova Metin

Testing and Tracing Lazy Functional Programs using QuickCheck and Hat

Comp 411 Principles of Programming Languages Lecture 34 Semantics of OO Languages. Corky Cartwright Swarat Chaudhuri November 30, 20111

Programming and Reasoning with Side-Effects in IDRIS

Description of Class Mutation Mutation Operators for Java

AP Computer Science Java Subset

Name: Class: Date: 9. The compiler ignores all comments they are there strictly for the convenience of anyone reading the program.

Harmless Advice. Daniel S Dantas Princeton University. with David Walker

The countdown problem

Debugging. Common Semantic Errors ESE112. Java Library. It is highly unlikely that you will write code that will work on the first go

Maar hoe moet het dan?

FUNDAMENTALS OF ARTIFICIAL INTELLIGENCE KNOWLEDGE REPRESENTATION AND NETWORKED SCHEMES

Special Directions for this Test

13 Classes & Objects with Constructors/Destructors

: provid.ir

opalang - Rapid & Secure Web Development

3. Mathematical Induction

Denotational design with type class morphisms (extended version)

Taming Wildcards in Java s Type System

ML for the Working Programmer

Computing Concepts with Java Essentials

The Relational Model. Ramakrishnan&Gehrke, Chapter 3 CS4320 1

Extensible Effects An Alternative to Monad Transformers

The Habit Programming Language: The Revised Preliminary Report

Designing with Exceptions. CSE219, Computer Science III Stony Brook University

Teaching Statement Richard A. Eisenberg

Java Application Developer Certificate Program Competencies

Cohort: BCA/07B/PT - BCA/06/PT - BCNS/06/FT - BCNS/05/FT - BIS/06/FT - BIS/05/FT - BSE/05/FT - BSE/04/PT-BSE/06/FT

AURA: A language with authorization and audit

Lecture Notes on Linear Search

Unboxed Polymorphic Objects for Functional Numerical Programming

How To Understand The Theory Of Computer Science

In order to understand Perl objects, you first need to understand references in Perl. See perlref for details.

Ralf Hinze Generic Programs and Proofs

Introduction to type systems

JAVA - INHERITANCE. extends is the keyword used to inherit the properties of a class. Below given is the syntax of extends keyword.

Design by Contract beyond class modelling

History OOP languages Year Language 1967 Simula Smalltalk

First-Class Type Classes

Making Standard ML a Practical Database Programming Language

Part VI. Object-relational Data Models

Cloud Haskell. Distributed Programming with. Andres Löh. 14 June 2013, Big Tech Day 6 Copyright 2013 Well-Typed LLP. .Well-Typed

Classes and Objects in Java Constructors. In creating objects of the type Fraction, we have used statements similar to the following:

Lecture 9. Semantic Analysis Scoping and Symbol Table

Transcription:

Advanced Functional Programming Andres Löh Department of Information and Computing Sciences Utrecht University March 23, 2009

11. Type Classes 11-1

This lecture 11 What are type classes? Qualified types Evidence translation Extensions to the class system: Functional dependencies Associated types 11-2

11.1 Introduction to type classes 11-3

Type classes 11.1 One of the features that makes Haskell unique. Predicates on types (but not types themselves!). Provide ad-hoc polymorphism or overloading. Extensible or open. Haskell 98 only allows unary predicates, but already allows classes that range over types of different kinds (Eq and Show vs. Functor and Monad). Lots of extensions. Can be translated into polymorphic lambda calculus F ω. 11-4

Classes and instances 11.1 A class declaration defines a predicate. Each member of a class supports a certain set of methods. An instance declaration declares some types to be in the class, and provides evidence of that fact by providing implementations for the methods. Depending on the situation, we may ask different questions about a type and a class: Is the type a member of the class (yes or no)? Why/how is the type a member of the class (give me evidence, please)? Functions that use methods get class constraints that are like proof obligations. 11-5

Parametric vs. ad-hoc polymorphism 11.1 Parametric polymorphism swap :: (a, b) (b, a) swap (x, y) = (y, x) Unconstrained variables can be instantiated to all types. No assumptions about the type can be made in the definition of the function. The function works uniformly for all types. Ad-hoc polymorphism between :: (Ord a) a a a Bool between x y z = x y y z 11-6 Constrained variables can only be instantiated to members of the class. Since each instance is specific to a type, the behaviour can differ vastly depending on the type that is used.

Restrictions 11.1 The Haskell 98 design is rather restrictive: 11-7 only one type parameter per class only one instance per type superclasses are possible, but the class hierarchy must not be cyclic instances can only be declared for simple types, types of the form T a 1... a n (where T is not a type synonym and a 1,..., a n are type variables). instance or class contexts may only be of the form C a (where a is a type variable). function contexts can only be of the form C (a t 1... t n) (where a is a type variable and t 1,..., t n are types possibly containing variables).

Examples: Restrictions 11.1 instance Eq a Eq [a] instance Eq [a] Eq [a] -- illegal instance Eq Int Eq [Int] -- illegal instance Eq a Eq (a, Bool) -- illegal instance Eq [[a]] -- illegal instance Eq String -- illegal (Eq (f Int)) f Int f Int Bool (Eq [Int]) [Int] [Int] Bool -- illegal (Eq [a]) [a] [a] Bool -- illegal 11-8

Examples: Restrictions 11.1 instance Eq a Eq [a] instance Eq [a] Eq [a] instance Eq Int Eq [Int] instance Eq a Eq (a, Bool) instance Eq [[a]] instance Eq String (Eq (f Int)) f Int f Int Bool (Eq [Int]) [Int] [Int] Bool (Eq [a]) [a] [a] Bool -- illegal -- illegal -- illegal -- illegal -- illegal -- illegal -- illegal 11-8 The restrictions ensure that instance resolution is efficient and terminates, and that contexts are always reduced as much as possible.

11.2 Qualified types 11-9

Introduction 11.2 Types with contexts are also called qualified types. Mark Jones describes a Theory of Qualified Types, which is a framework of which the Haskell type class system is one specific instance. Qualified types can also be used to track other properties of types: presence or absence of labels in extensible records, subtyping conditions type equality constraints presence or absence of effects (see Hage, Holdermans, Middelkoop, ICFP 2007) 11-10

Example 11.2 Some contexts imply other contexts: Eq Int Eq [Int] Eq Bool, Ord Int Ord Int Eq Int The latter holds if we assume globally that an instance for Eq Int exists. 11-11

Entailment 11.2 Entailment ( ) is a relation on two contexts. The following rules are given by the framework for qualified types: Q P P Q (mono) P Q Q R P R (trans) P Q ϕ is a substitution ϕ P ϕ Q (closure) 11-12

Type class entailment 11.2 Only these two rules are specific to the type class system: P π P Q class Q π P Q instance Q π P π (super) (inst) 11-13

Type class entailment 11.2 Only these two rules are specific to the type class system: P π P Q class Q π P Q instance Q π P π (super) (inst) 11-13 Example class Eq a Ord a Ord a Eq a (super) The direction of the arrow is somewhat misleading. Not Eq a implies Ord a, but the other way around. Read: only if Eq a, we can define Ord a.

Validity of instances 11.2 Instance declarations must adhere to the class hierarchy: class Q π P ϕ Q instance P ϕ π is valid (valid) 11-14

Example: validity of instances 11.2 class (Eq a, Show a) Num a class Foo a Bar a class Foo a instance (Eq a, Show a) Foo [a] instance Num a Bar [a] 11-15

Example: validity of instances 11.2 class (Eq a, Show a) Num a class Foo a Bar a class Foo a instance (Eq a, Show a) Foo [a] instance Num a Bar [a]... c Foo a Bar a Num a Foo [a] (valid) i Num a Bar [a] is valid 11-15

Example: validity of instances 11.2 class (Eq a, Show a) Num a class Foo a Bar a class Foo a instance (Eq a, Show a) Foo [a] instance Num a Bar [a]... c Foo a Bar a Num a Foo [a] (valid) i Num a Bar [a] is valid c (Eq a, Show a) Num a (class) Num a (Eq a, Show a) i (Eq a, Show a) Foo [a] (inst) Num a Foo [a] 11-15

Type rules 11.2 Usually, type rules are of the form Γ e :: τ where Γ is an environment mapping identifiers to types, e is an expression, and t is a (possibly polymorphic) type. 11-16

Type rules 11.2 Usually, type rules are of the form Γ e :: τ where Γ is an environment mapping identifiers to types, e is an expression, and t is a (possibly polymorphic) type. With qualified types, type rules are of the form P Γ e :: τ where P is a context representing (local) knowledge, and τ is a (possibly polymorphic, possibly overloaded) type. 11-16

Context reduction 11.2 P Γ e :: π ρ P π P Γ e :: ρ (context-reduce) Haskell s type inference applies this rule where adequate: (= =) :: (Eq a) a a Bool hello :: String hello = = hello :: Bool Requires Eq String. 11-17

Context introduction 11.2 P, π Γ e :: ρ P Γ e :: π ρ (context-intro) Haskell s type inference applies this rule when generalizing in a let or a toplevel declaration: between x y z = x y y z Inferred to be of type (Ord a) a a a Bool. 11-18

A strange error 11.2 Using the following definition in a Haskell module results in a type error: maxlist = maximum 11-19

A strange error 11.2 Using the following definition in a Haskell module results in a type error: maxlist = maximum Monomorphism restriction A toplevel value without an explicit type signature is never overloaded. 11-19

11.3 Evidence translation 11-20

Translating type classes 11.3 Type classes can be translated into a lambda calculus without type classes as follows: Each class declaration defines a record type (also called dictionary). Each instance declaration defines a function resulting in the dictionary type. Each method call selects the corresponding field from the dictionary. Context introduction corresponds to the abstraction of function arguments of dictionary type. Context reduction corresponds to the implicit construction and application of a dictionary argument. 11-21

Example: evidence translation 11.3 class E a where e :: a a Bool instance E Int where e = (= =) instance E a E [a] where e [ ] [ ] = True e (x : xs) (y : ys) = e x y e xs ys e = False member :: E a a [a] Bool member [ ] = False member a (x : xs) = e a x member a xs duplicates :: E a [a] Bool duplicates [ ] = False duplicates (x : xs) = member x xs duplicates xs is = [[ ], [1], [2], [1, 2], [2, 1]] :: [[Int]] main = (duplicates is, duplicates (concat is)) 11-22

Example: evidence translation 11.3 class E a where e :: a a Bool instance E Int where e = (= =) instance E a E [a] where e [ ] [ ] = True e (x : xs) (y : ys) = e x y e xs ys e = False member :: E a a [a] Bool member [ ] = False member a (x : xs) = e a x member a xs duplicates :: E a [a] Bool duplicates [ ] = False duplicates (x : xs) = member x xs duplicates xs is = [[ ], [1], [2], [1, 2], [2, 1]] :: [[Int]] main = (duplicates is, duplicates (concat is)) data E a = E {e :: a a Bool} e Int :: E Int e Int = E {e = (= =)} e List :: E a E [a] e List e a = E {e = e } where e [ ] [ ] = True e (x : xs) (y : ys) = e e a x y e (e List e a) xs ys e = False member :: E a a [a] Bool member e a [ ] = False member e a a (x : xs) = e e a a x member e a a xs duplicates :: E a [a] Bool duplicates e a [ ] = False duplicates e a (x : xs) = member e a x xs duplicates e a xs is = [[ ], [1], [2], [1, 2], [2, 1]] :: [[Int]] main = (duplicates (e List e Int ) is, duplicates e Int (concat is)) 11-22

Dictionaries and superclasses 11.3 Dictionaries contain dictionaries of their superclasses: class Eq a Ord a data Ord a = Ord {eq :: Eq a, compare :: a a Ordering,...} 11-23

Dictionaries and polymorphic methods 11.3 class Functor f where fmap :: (a b) f a f b data Functor f = Functor {fmap :: a b.(a b) f a f b} The field fmap is a polymorphic field. Note that this is equivalent to the non-record data Functor f = Functor ( a b.(a b) f a f b) and different from the existential type data Functor f = a b.functor ((a b) f a f b) 11-24

Polymorphic fields vs. existential types 11.3 An existential type hides a specific type. A polymorphic field stores a polymorphic function. data Functor f = Functor ( a b.(a b) f a f b) data Functor f = a b.functor ((a b) f a f b) Functor :: ( a b.(a b) f a f b) Functor f Functor :: a b.((a b) f a f b) Functor f The constructor Functor takes a polymorphic function as an argument. The type of Functor is a so-called rank-2 polymorphic type. More in the next lecture. 11-25

Type-directed translation 11.3 Evidence translation is a byproduct of type inference type rules can be augmented with translated terms. New form of rules: P Γ e e :: τ P Q e Modified rules: P Γ e e :: π ρ P π e π P Γ e e e π :: ρ (context-reduce) 11-26 P, e π :: π Γ e e :: ρ P Γ e λe π e :: π ρ (context-intro)

Monomorphism restriction revisited 11.3 Question Why the monomorphism restriction? 11-27

Monomorphism restriction revisited 11.3 Question Why the monomorphism restriction? Answer To prevent unexpected inefficiency or loss of sharing. 11-27

11.4 Defaulting 11-28

Defaulting of numeric classes 11.4 Main : t 42 42 :: (Num t) t Defining x = 42 does not produce an error despite the monomorphism restriction. 11-29

Defaulting of numeric classes 11.4 Main : t 42 42 :: (Num t) t Defining x = 42 does not produce an error despite the monomorphism restriction. Haskell performs defaulting of Num constraints and chooses Integer in this case. 11-29

GHCi defaulting 11.4 GHCi (not Haskell in general) also performs defaulting of other constraints than Num, to (): Main let maxlist = maximum Main : t maxlist maxlist :: [()] () Prevents annoying errors (show [ ]). Can lead to subtle mistakes (QuickCheck properties). 11-30

Ambiguity and coherence 11.4 Question What is the type of the following expression? show read 11-31

Ambiguity and coherence (contd.) 11.4 Such an expression is called ambiguous because it has a constraint mentioning a variable that does not occur in the rest of the type: (Show a, Read a) String String Choosing different types can lead to different behaviour. Ambiguous types are disallowed by Haskell if they cannot be defaulted. Ambiguity is a form of incoherence: if allowed, multiple translations of a program with possibly different behaviour are possible. 11-32

Specialization 11.4 A specialization is a partially evaluated copy of an overloaded function trades code size for more efficiency. GHC provides a pragma for this purpose: between :: (Ord a) a a a Bool -# SPECIALISE between :: Char Char Char Bool #- causes between Char :: Char Char Char Bool between Char = between ord Char to be generated and used whenever between ord Char would normally be used. 11-33 Using a RULES pragma, one can even provide different implementations for specific types. (Why useful?)

11.5 Extensions 11-34

Extensions to the class system 11.5 Nearly all Haskell-98 restrictions to the class system can be lifted. The price: worse properties of the program, less predictability, worse error messages, partially unclear semantics and interactions, possible compiler bugs. Nevertheless, some extensions are useful, and it is important to explore the design space in order to find an optimum. 11-35

Flexible instances and contexts 11.5 Lifts the restrictions on the shape of instances and contexts. 11-36

Overlapping instances 11.5 Allows overlapping instance definitions such as instance Foo a Foo [a] instance Foo [Int] Two possibilities to construct Foo [Int] if instance Foo Int is also given. Both possibilities might lead to different behaviour (incoherence). The most specific instance is chosen. 11-37

Overlapping instances and context reduction 11.5 What about? foo :: (Foo a) a a test x xs = foo (x : xs) 11-38

Overlapping instances and context reduction 11.5 What about? foo :: (Foo a) a a test x xs = foo (x : xs) Reducing the context of test from Foo [a] to Foo a prevents Foo [Int] from being selected! Delay? 11-38

Incoherent instances 11.5 If you let GHC infer a type for test in foo :: (Foo a) a a test x xs = foo (x : xs) you get (Foo [a]) a [a] [a], i.e., GHC tries to delay the decision. 11-39

Incoherent instances (contd.) 11.5 If you specify test :: Foo a a [a] [a] you get an error unless you tell GHC to allow incoherent instances. Advice With incoherent instances, it is very hard to predict how the instances are built. Allow incoherent instances only if you make sure that different ways to construct an instance have the same behaviour! 11-40

Undecidable instances 11.5 With undecidable instances, it is no longer required that context reduction actually reduces the context. The type checker may loop: instance Foo [[a]] Foo [a] 11-41

Next lecture 11.5 Next lecture will be on GADTs (generalized algebraic data types). Read: Chung-chieh Shan. Sexy types in action. Next week: lectures will be given by José Pedro Magalhães. Second student talk session: Monday, April 6. Programming project deadline: Sunday, April 5 (strict). 11-42