Advanced Functional Programming

Similar documents
Lecture #13: Type Inference and Unification. Typing In the Language ML. Type Inference. Doing Type Inference

Overloading, Type Classes, and Algebraic Datatypes

Arbitrary-rank polymorphism in (GHC) Haskell

Advanced Functional Programming

Functional Programming - 2. Higher Order Functions

Lambda Calculus and Type Inference

Type Processing by Constraint Reasoning

Chapter 22: Type Reconstruction (Type Inference)

Exercise 1 ( = 24 points)

Lecture #23: Conversion and Type Inference

Haskell Types, Classes, and Functions, Currying, and Polymorphism

Conversion vs. Subtyping. Lecture #23: Conversion and Type Inference. Integer Conversions. Conversions: Implicit vs. Explicit. Object x = "Hello";

Types and Type Inference

Exercise 1 ( = 22 points)

Optimising Functional Programming Languages. Max Bolingbroke, Cambridge University CPRG Lectures 2010

Haskell An Introduction

CS 320 Midterm Exam. Fall 2018

Lecture 4: Higher Order Functions

CS153: Compilers Lecture 14: Type Checking

A Second Look At ML. Chapter Seven Modern Programming Languages, 2nd ed. 1

CSE 3302 Programming Languages Lecture 8: Functional Programming

CS 320: Concepts of Programming Languages

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

CS 11 Haskell track: lecture 1

Exercise 1 ( = 18 points)

Programming in Omega Part 1. Tim Sheard Portland State University

Type Systems, Type Inference, and Polymorphism

Programming in Omega Part 2. Tim Sheard Portland State University

SML A F unctional Functional Language Language Lecture 19

CSCI-GA Scripting Languages

Polymorphism and Type Inference

Exercise 1 (2+2+2 points)

GADTs. GADTs in Haskell

Polymorphism and System-F (OV)

CSE 130: Programming Languages. Polymorphism. Ranjit Jhala UC San Diego

Theorem Proving Principles, Techniques, Applications Recursion

Wellesley College CS251 Programming Languages Spring, 2000 FINAL EXAM REVIEW PROBLEM SOLUTIONS

CS 457/557: Functional Languages

CSE341, Fall 2011, Midterm Examination October 31, 2011

02157 Functional Programming. Michael R. Ha. Disjoint Unions and Higher-order list functions. Michael R. Hansen

Advanced Type System Features Tom Schrijvers. Leuven Haskell User Group

Lambda Calculus and Type Inference

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

The List Datatype. CSc 372. Comparative Programming Languages. 6 : Haskell Lists. Department of Computer Science University of Arizona

Principles of Programming Languages

Metaprogramming assignment 3

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

Introduction to Haskell

Tuples. CMSC 330: Organization of Programming Languages. Examples With Tuples. Another Example

Type Checking and Type Inference

Proving Theorems with Athena

INFOB3TC Solutions for the Exam

Lambda Calculi With Polymorphism

Type-indexed functions in Generic Haskell

CSE341, Fall 2011, Midterm Examination October 31, 2011

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

Type families and data kinds

Functional Programming. Pure Functional Programming

GADTs. Wouter Swierstra and Alejandro Serrano. Advanced functional programming - Lecture 7. [Faculty of Science Information and Computing Sciences]

Mini-ML. CS 502 Lecture 2 8/28/08

Ornaments in ML. Thomas Williams, Didier Rémy. April 18, Inria - Gallium

Advanced Programming Handout 7. Monads and Friends (SOE Chapter 18)

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

Types and Type Inference

Imperative languages

Principles of Programming Languages COMP251: Functional Programming in Scheme (and LISP)

GADTs. Alejandro Serrano. AFP Summer School. [Faculty of Science Information and Computing Sciences]

Overview. Elements of Programming Languages. Another example. Consider the humble identity function

Functional Programming. Overview. Topics. Definition n-th Fibonacci Number. Graph

Lecture 2: List algorithms using recursion and list comprehensions

Programming Language Concepts: Lecture 14

02157 Functional Programming. Michael R. Ha. Lecture 2: Functions, Types and Lists. Michael R. Hansen

The Typed Racket Guide

6.184 Lecture 4. Interpretation. Tweaked by Ben Vandiver Compiled by Mike Phillips Original material by Eric Grimson

02157 Functional Programming Tagged values and Higher-order list functions

CSE341 Spring 2017, Final Examination June 8, 2017

All the operations used in the expression are over integers. a takes a pair as argument. (a pair is also a tuple, or more specifically, a 2-tuple)

The Haskell HOP: Higher-order Programming

Typed Racket: Racket with Static Types

CIS 500: Software Foundations

CMSC 330: Organization of Programming Languages. Operational Semantics

Introduction to Programming, Aug-Dec 2006

Introduction to Functional Programming in Haskell 1 / 56

CIS 500 Software Foundations. Midterm I. (Standard and advanced versions together) October 1, 2013 Answer key

According to Larry Wall (designer of PERL): a language by geniuses! for geniuses. Lecture 7: Haskell. Haskell 98. Haskell (cont) - Type-safe!

Scheme Basics > (butfirst '(help!)) ()

Simple Unification-based Type Inference for GADTs

Exercises on ML. Programming Languages. Chanseok Oh

Graphical Untyped Lambda Calculus Interactive Interpreter

Processadors de Llenguatge II. Functional Paradigm. Pratt A.7 Robert Harper s SML tutorial (Sec II)

Qualified Types for MLF

Handout 2 August 25, 2008

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

Introduction to ML. Based on materials by Vitaly Shmatikov. General-purpose, non-c-like, non-oo language. Related languages: Haskell, Ocaml, F#,

PROGRAMMING IN HASKELL. Chapter 2 - First Steps

Type Systems. Parametric Polymorphism. 1. Recall Let-Polymorphism. 1. Recall Let-Polymorphism. Lecture 9 Dec. 15th, 2004 Sebastian Maneth

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

Haskell Refresher Informatics 2D

IA014: Advanced Functional Programming

Typed Scheme: Scheme with Static Types

Transcription:

Advanced Functional Programming Tim Sheard Polymorphism Hindley-Milner Polymorphism Rank 2 polymorphism Tim Sheard 1

Polymorphism A function is polymorphic if it can work on any kind of argument. f x = (x,x) Main> :t f f :: a -> (a,a) In essence it makes no reference to the value of its argument, it only manipulates it abstractly. Tim Sheard 2

Local Polymorphism Polymorphism can be scoped. g x = let f = \ y -> (x,y) w1 = f "z" w2 = f True in (x,f) What type does f have? forall b. b -> (a,b) Main> :t g g :: a -> (a,b -> (a,b)) Tim Sheard 3

Let as function application Let is often defined in terms of application let x = e in y == (\ x -> y) e But there are difference in how let is typed. g x = (\ f -> let w1 = f "z" w2 = f True in (x,f)) (\ y -> (x,y)) g x = let f = \ y -> (x,y) w1 = f "z" w2 = f True in (x,f) ERROR " (line 12): Type error in application *** Expression : f True *** Term : True *** Type : Bool *** Does not match : [Char] Tim Sheard 4

Let polymorphism Let-bound functions can be polymorphic, but lambda-bound arguments cannot. This is the essence of Hindley-Milner polymorphism. This means no function can be defined to take an argument which must be polymorphic No argument can ever be used in more than none polymorphic context. All types have the forall on the outermost forall a. ( x -> (a -> b) -> (x,b)) as opposed to x -> (forall a. a -> b) -> (x,b) Tim Sheard 5

Example h f x = let w1 = f "z" w2 = f True in (w1,w2) ERROR (line 18): Type error in application *** Expression : f True *** Term : True *** Type : Bool *** Does not match : [Char] Tim Sheard 6

Rank 2 polymorphism Rank 2 polymorphism relaxes some of this restriction. h :: (forall a. a -> a) -> x -> (x,bool) h f x = let w1 = f x w2 = f True in (w1,w2) forall's can be in the back-end of an arrow, but never the front end. (forall...) -> ((forall...) -> z) Tim Sheard 7

Type inference Type inference of polymorphic arguments is undecidable. If we want rank 2 polymorphism, we must use type annotations. Type-checking of rank 2 polymorphism is decidable What kind of annotations must we give? The answer to this is hard to find. Giving the full signature of every function is enough. Is there any compromise using less information? Tim Sheard 8

Full application In order to do type checking, rank 2 functions must be fully applied. That is all polymorphic arguments must be supplied. ex2 = (4,h) (line 28): Use of h requires at least 1 argument Arguments to rank 2 functions must really be polymorphic. ex4 = h id 5 Main> :t ex4 ex4 :: (Integer,Bool) ex3 = h ( \ x -> 1) 5 ERROR (line 33): Cannot justify constraints in application *** Expression : \x -> 1 *** Type : b -> b *** Given context : () *** Constraints : Num b Tim Sheard 9

Rank 2 Data Constructors Data Constructors with polymorphic components give enough information to do type inference. data Test x = C (forall a. a -> x -> (a,x)) x ex5 = C (\ a x -> (a,x+1)) 3 ex6 = C (\ a x -> (a,not x)) True f3 (C h n) w = h "z" w What is the type of ex5, ex6, and f3? Tim Sheard 10

Church Numerals Recognize the data type definition for natural numbers data Nat = Z S Nat The catamorphism for Nat is the natural recursion pattern for Nat (sometimes called the fold) catanat zobj sfun Z = zobj catanat zobj sfun (S x) = sfun (catanat zobj sfun x) Many functions on Nat can be defined in terms of catanat plus x y = catanat y S x ex7 = plus (S Z) (S (S Z)) Main> ex7 S (S (S Z)) Tim Sheard 11

CataNat for multiplication times x y = catanat Z (plus x) y one = S Z two = S one three = S two ex8 = times two three Main> ex8 S (S (S (S (S (S Z))))) Tim Sheard 12

Nat as a rank 2 function data N = N (forall z. z -> (z -> z) -> z) catan zobj sfun (N f) = f zobj sfun n0 = N(\ z s -> z) n1 = N(\ z s -> s z) n2 = N(\ z s -> s(s z)) n3 = N(\ z s -> s(s(s z))) n4 = N(\ z s -> s(s(s(s z)))) n2int n = catan 0 (+1) n ex9 = n2int n3 Main> ex9 3 Tim Sheard 13

Plus in data type N --plus x y = catanat y S x succn :: N -> N succn (N f) = N(\ z s -> s(f z s)) plusn :: N -> N -> N plusn x y = catan y succn x ex10 = n2int (plusn n2 n3) Main> ex10 5 Tim Sheard 14

Church Numerals for List data L1 a = L1 (forall b. b -> (a -> b -> b) -> b) -- [1,2,3,4] ex1 = L1 ( \ n c -> c 1 (c 2 (c 3 (c 4 n)))) tolist (L1 f) = f [] (:) ex11 = tolist ex1 Main> :t ex11 ex11 :: [Integer] Main> ex11 [1,2,3,4] Tim Sheard 15

Append in "church numeral" lists catalist nobj cfun [] = nobj catalist nobj cfun (x:xs) = cfun x (catalist nobj cfun) catal nobj cfun (L1 f) = f nobj cfun cons x (L1 f) = L1(\ n c -> c x (f n c)) app x y = catal y cons x ex12 = app ex1 ex1 ex13 = tolist ex12 Main> ex13 [1,2,3,4,1,2,3,4] Tim Sheard 16

lists, fusion, and rank 2 polymorphism This form of rank 2 polymorphism has been exploited to justify fusion or deforestation. Consider sum(map (+1) (upto 3)) sum(map (+1) [1,2,3]) sum[2,3,4] 9 Produces, then consumes a bunch of intermediate lists, which never needed to be produced at all Tim Sheard 17

Discovering fusion How can we take an arbitrary expression about lists like: sum(map (+1) (upto 3)) and discover an equivalent expression that does not build the intermediate lists? Answer: write functions in terms of abstract recursion patterns, and rank-2 representations of lists. cata : b -> (a -> b -> b) -> [a] -> b build: (forall b. b -> (a -> b -> b) -> b) -> [a] with the law: cata n c (build f) == f n c Tim Sheard 18

build :: (forall b. b -> (a -> b -> b) -> b) -> [a] build f = f [] (:) cata nobj cfun [] = nobj cata nobj cfun (x:xs) = cfun x (cata nobj cfun xs) upto x = build(\ n c -> let h m = if m>x then n else c m (h (m+1)) in h 1) mapx f x = build(\ n c -> cata n (\ y ys -> c (f y) ys) x) sumx xs = cata 0 (+) xs Tim Sheard 19

sum(map (+1) (upto 3)) == sum(map (+1) (build(\ n c -> let h m = if m>3 then n else c m (h (m+1)) in h 1) == sum(build(\ n c -> cata n (\ y ys -> c (f y) ys) (build(\ n c -> let h m = if m>3 then n else c m (h (m+1)) in h 1))) == Tim Sheard 20

sum(build(\ n c -> let h m = if m>3 then n else c (f m) (h (m+1)) in h 1)) == cata 0 (+) (build(\ n c -> let h m = if m>3 then n else c (f m) (h (m+1)) in h 1)) == let h m = if m>3 then 0 else (f m) + (h (m+1))] in h 1 == sum(map (+1) (upto 3) Tim Sheard 21

We can encode this as such data List a = Nil Cons a (List a) Build (forall b. b -> (a -> b -> b) -> b) cataz nobj cfun Nil = nobj cataz nobj cfun (Cons y ys) = cfun y (cataz nobj cfun ys) cataz nobj cfun (Build f) = f nobj cfun uptoz x = Build(\ n c -> let h m = if m>x then n else c m (h (m+1)) in h 1) mapz f x = Build(\ n c -> cataz n (\ y ys -> c (f y) ys) x) sumz xs = cataz 0 (+) xs Tim Sheard 22

Results ex14 = sumz(mapz (+1) (uptoz 3)) ex15 = sum(map (+1) ([1..3])) Main> ex14 9 (81 reductions, 177 cells) Main> ex15 9 (111 reductions, 197 cells) Tim Sheard 23

Type inference and Hindley-Milner How is type inference done? Structural recursion over a term. Uses an environment which maps variables to their types Returns a computation in a monad type infer :: Exp -> Env -> M Type What does the Env look like partial function from Name -> Scheme Scheme is an encoding of a Hindley-Milner polymorphic type. All the forall's to the outermost position. Often implemented as a list Tim Sheard 24

How is Env used g x = let f = \ y -> (x,y) w1 = f "z" w2 = f True in (x,f) Every instance of a variable is given a new instance of its type. Let Capital letters (A,B,C,A1,B1,C1,...) indicate new fresh type variables. In the box suppose f:: forall a. a -> (x,a) Tim Sheard 25

Instantiation g x = let f = \ y -> (x,y) w1 = f "z" w2 = f True in (x,f) the f in (f "z") A1 -> (x,a1) A1 gets "bound" to String the f in (f True) A2 -> (x,a2) A2 gets "bound" to Bool the f in (x,f) A3 -> (x,a3) A3 remains "unbound" Tim Sheard 26

Binding Introduction g x = let f = \ y -> (x,y) w1 = f "z" w2 = f True in (x,f) Every Bound program variable is assigned a new fresh type variable {g::e1} {g::e1, x::a1} {g::e1, x::a1, f::b1, y::c1 } {g::e1, x::a1, f::b1, w1::d1} {g::e1, x::a1, f::b1, w1::d1, w2::f1} Tim Sheard 27

Type inference g x = let f = \ y -> (x,y) w1 = f "z" w2 = f True in (x,f) {g::e1, x::a1, f::b1} As type inference proceeds type variables become "bound", thus the type of (\ y -> (x,y)) becomes C1 -> (A1,C1) Since f = (\ y -> (x,y)) the type variable B1 could be bound to C1 -> (A1,C1) Tim Sheard 28

Generalization But the rules of Hindley-Milner type inference say for every let-bound variable generalize it on all the type variables not in the current scope. g x = let f = ((\ y -> (x,y)) :: C1 -> (A1,C1)) w1 = f "z" w2 = f True in (x,f) {g::e1, x::a1, f::b1} Since C1 does not appear in the types of the current scope, it is generalized and the type of f (B1) becomes polymorphic. {g::e1, x::a1, f::forall c. c -> (A1,c)} Tim Sheard 29

The monad of Type Inference Methods required unify:: Type -> Type -> M () lambdaext :: Name -> Env -> M(Env,Type) letext:: Name -> Env -> M(Env,Scheme) lookup:: Name -> Env -> Scheme instantiate:: Scheme -> M Type generalize:: Type -> Env -> M Scheme freshtypevar:: M Type Tim Sheard 30

Rank 2 polymorphism The Type of runst is a rank 2 polymorphic type runst :: a. ( s. ST s a) -> a The forall is not all the way to the outside. There are other uses of rank 2 types. Tim Sheard 31