Programming Language Concepts: Lecture 14

Similar documents
Introduction to Programming, Aug-Dec 2006

Introduction to Programming: Lecture 3

Functional Programming in Haskell Part I : Basics

Functional Programming in Haskell Part 2 : Abstract dataypes and infinite structures

Introduction to Programming, Aug-Dec 2008

PROGRAMMING IN HASKELL. CS Chapter 6 - Recursive Functions

PROGRAMMING IN HASKELL. Chapter 5 - List Comprehensions

Lecture 19: Functions, Types and Data Structures in Haskell

PROGRAMMING IN HASKELL. Chapter 2 - First Steps

Haskell 98 in short! CPSC 449 Principles of Programming Languages

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

Lecture 10 September 11, 2017

CS 320: Concepts of Programming Languages

Shell CSCE 314 TAMU. Functions continued

It is better to have 100 functions operate one one data structure, than 10 functions on 10 data structures. A. Perlis

Informatics 1 Functional Programming Lecture 7. Map, filter, fold. Don Sannella University of Edinburgh

CITS3211 FUNCTIONAL PROGRAMMING. 7. Lazy evaluation and infinite lists

A general introduction to Functional Programming using Haskell

CSCE 314 TAMU Fall CSCE 314: Programming Languages Dr. Flemming Andersen. Haskell Functions

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

Logic Programming: Lecture 1

Programming Language Concepts: Lecture 19

Types and Type Inference

CS 11 Haskell track: lecture 1

Typed Racket: Racket with Static Types

COP4020 Programming Languages. Functional Programming Prof. Robert van Engelen

Haskell through HUGS THE BASICS

Types, Type Inference and Unification

Introduction to Programming: Lecture 6

Programming in Haskell Aug-Nov 2015

Haske k ll An introduction to Functional functional programming using Haskell Purely Lazy Example: QuickSort in Java Example: QuickSort in Haskell

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

Advanced Topics in Programming Languages Lecture 2 - Introduction to Haskell

The Typed Racket Guide

Programming in Haskell Aug-Nov 2015

Types and Type Inference

CITS3211 FUNCTIONAL PROGRAMMING

An introduction introduction to functional functional programming programming using usin Haskell

Functional Programming. Overview. Topics. Recall λ-terms. Examples

Haskell: Lists. CS F331 Programming Languages CSCE A331 Programming Language Concepts Lecture Slides Friday, February 24, Glenn G.

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

Functional Programming

Logic - CM0845 Introduction to Haskell

Lecture #23: Conversion and Type Inference

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

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

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

CSE 3302 Programming Languages Lecture 8: Functional Programming

Lecture 5: Lazy Evaluation and Infinite Data Structures

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

Principles of Programming Languages

CSCE 314 TAMU Fall CSCE 314: Programming Languages Dr. Flemming Andersen. Haskell Basics

Programming Languages Fall 2013

CS 440: Programming Languages and Translators, Spring 2019 Mon

CSCE 314 Programming Languages

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

Standard prelude. Appendix A. A.1 Classes

Shell CSCE 314 TAMU. Haskell Functions

CSc 372. Comparative Programming Languages. 15 : Haskell List Comprehension. Department of Computer Science University of Arizona

Introduction. chapter Functions

Lambda Calculus and Type Inference

CSCE 314 Programming Languages

A list is a finite sequence of elements. Elements may appear more than once

Functional Programming in Haskell Prof. Madhavan Mukund and S. P. Suresh Chennai Mathematical Institute

Logical Methods in... using Haskell Getting Started

FUNCTIONAL PROGRAMMING 1 HASKELL BASICS

Shell CSCE 314 TAMU. Higher Order Functions

INTRODUCTION TO HASKELL

Programming Language Concepts: Lecture 22

SML A F unctional Functional Language Language Lecture 19

Lecture 1 August 9, 2017

Exercise 1 ( = 22 points)

This example highlights the difference between imperative and functional programming. The imperative programming solution is based on an accumulator

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

Introduction to Functional Programming in Haskell 1 / 56

CSc 372. Comparative Programming Languages. 8 : Haskell Function Examples. Department of Computer Science University of Arizona

CS 457/557: Functional Languages

Higher Order Functions in Haskell

1.3. Conditional expressions To express case distinctions like

CS 4110 Programming Languages & Logics. Lecture 17 Programming in the λ-calculus

Lecture 2: List algorithms using recursion and list comprehensions

Functional Programming Languages (FPL)

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

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

INTRODUCTION TO FUNCTIONAL PROGRAMMING

Haskell An Introduction

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

CSc 372 Comparative Programming Languages

Introduction to OCaml

Type Systems, Type Inference, and Polymorphism

Defining Functions. CSc 372. Comparative Programming Languages. 5 : Haskell Function Definitions. Department of Computer Science University of Arizona

Imperative languages

PROGRAMMING IN HASKELL. Chapter 2 - First Steps

PROGRAMMING IN HASKELL. Chapter 2 - First Steps

Programming Languages

Solution sheet 1. Introduction. Exercise 1 - Types of values. Exercise 2 - Constructors

CS 360: Programming Languages Lecture 10: Introduction to Haskell

Haskell Programs. Haskell Fundamentals. What are Types? Some Very Basic Types. Types are very important in Haskell:

Programming Systems in Artificial Intelligence Functional Programming

cs242 Kathleen Fisher Reading: Concepts in Programming Languages, Chapter 6 Thanks to John Mitchell for some of these slides.

Transcription:

Programming Language Concepts: Lecture 14 Madhavan Mukund Chennai Mathematical Institute madhavan@cmi.ac.in http://www.cmi.ac.in/~madhavan/courses/pl2009 PLC 2009, Lecture 14, 11 March 2009

Function programming A quick review of Haskell The (untyped) λ-calculus Polymorphic typed λ-calculus and type inference

Haskell Strongly typed functional programming language

Haskell Strongly typed functional programming language Functions transform inputs to outputs: x f f(x)

Haskell Strongly typed functional programming language Functions transform inputs to outputs: x f f(x) A Haskell program consists of rules to produce an output from an input

Haskell Strongly typed functional programming language Functions transform inputs to outputs: x f f(x) A Haskell program consists of rules to produce an output from an input Computation is the process of applying the rules described by a program

Defining functions A function is a black box: x f f(x) Internal description of function f has two parts: 1. Types of inputs and outputs 2. Rule for computing the output from the input Example: sqr :: Int -> Int Type definition sqr : Z Z sqr x = x^2 Computation rule x x 2

Basic types in Haskell Int Integers Float Char Bool Operations +, -, * Functions div, mod Note: / :: Int -> Int -> Float Values written in single quotes z, &,... Values True and False. Operations &&,, not

Functions with multiple inputs plus(m,n) = m + n plus : Z Z Z, or plus : R Z R Need to know arity of functions Instead, assume all functions take only one argument!

Functions with multiple inputs plus(m,n) = m + n plus : Z Z Z, or plus : R Z R Need to know arity of functions Instead, assume all functions take only one argument! m plus n plus m m+n Type of plus plus m: input is Int, output is Int plus: input is Int, output is a function Int -> Int plus :: Int -> (Int -> Int) plus m n = m + n

Functions with multiple inputs... plus m n p = m + n + p m plus n plus m p plus m n m+n+p plus m n p :: Int -> (Int -> (Int -> Int))

Functions with multiple inputs... plus m n p = m + n + p m plus n plus m p plus m n m+n+p plus m n p :: Int -> (Int -> (Int -> Int)) f x1 x2...xn = y x1::t1, x2::t2,..., xn::tn, y::t f::t1 -> (t2 -> (...(tn -> t)...))

Functions with multiple inputs... Function application associates to left f x1 x2...xn (...((f x1) x2)...xn) Arrows in function type associate to right f :: t1 -> t2 ->...tn -> t f :: t1 -> (t2 -> (...(tn -> t)...))

Functions with multiple inputs... Function application associates to left f x1 x2...xn (...((f x1) x2)...xn) Arrows in function type associate to right f :: t1 -> t2 ->...tn -> t f :: t1 -> (t2 -> (...(tn -> t)...)) Writing functions with one argument at a time = currying Haskell Curry, famous logician, lends name to Haskell Currying actually invented by Schönfinkel!

Defining functions Boolean expressions xor :: Bool -> Bool -> Bool xor b1 b2 = (b1 && (not b2)) ((not b1) && b2) middlebiggest :: Int -> Int -> Int -> Bool middlebiggest x y z = (x <= y) && (z <= y)

Defining functions Boolean expressions xor :: Bool -> Bool -> Bool xor b1 b2 = (b1 && (not b2)) ((not b1) && b2) middlebiggest :: Int -> Int -> Int -> Bool middlebiggest x y z = (x <= y) && (z <= y) ==, /=, <, <=, >, >=, /=

Definition by cases: Pattern matching Can define xor b1 b2 by listing out all combinations if b1 && not(b2) then True else if not(b1) && b2 then True else False

Definition by cases: Pattern matching Can define xor b1 b2 by listing out all combinations if b1 && not(b2) then True else if not(b1) && b2 then True else False Instead, multiple definitions, with pattern matching xor :: Bool -> Bool -> Bool xor True False = True xor False True = True xor b1 b2 = False

Definition by cases: Pattern matching Can define xor b1 b2 by listing out all combinations if b1 && not(b2) then True else if not(b1) && b2 then True else False Instead, multiple definitions, with pattern matching xor :: Bool -> Bool -> Bool xor True False = True xor False True = True xor b1 b2 = False When does an invocation match a definition? If definition argument is a variable, any value supplied matches (and is substituted for that variable) If definition argument is a constant, the value supplied must be the same constant

Definition by cases: Pattern matching Can define xor b1 b2 by listing out all combinations if b1 && not(b2) then True else if not(b1) && b2 then True else False Instead, multiple definitions, with pattern matching xor :: Bool -> Bool -> Bool xor True False = True xor False True = True xor b1 b2 = False When does an invocation match a definition? If definition argument is a variable, any value supplied matches (and is substituted for that variable) If definition argument is a constant, the value supplied must be the same constant Use first definition that matches, top to bottom

Defining functions... Functions are often defined inductively Base case: Explicit value for f (0) Inductive step: Define f (n) in terms of f (n 1),..., f (0)

Defining functions... Functions are often defined inductively Base case: Explicit value for f (0) Inductive step: Define f (n) in terms of f (n 1),..., f (0) For example, factorial is usually defined inductively 0! = 1 n! = n (n 1)!

Defining functions... Functions are often defined inductively Base case: Explicit value for f (0) Inductive step: Define f (n) in terms of f (n 1),..., f (0) For example, factorial is usually defined inductively 0! = 1 n! = n (n 1)! Use pattern matching to achieve this in Haskell factorial :: Int -> Int factorial 0 = 1 factorial n = n * (factorial (n-1))

Defining functions... Functions are often defined inductively Base case: Explicit value for f (0) Inductive step: Define f (n) in terms of f (n 1),..., f (0) For example, factorial is usually defined inductively 0! = 1 n! = n (n 1)! Use pattern matching to achieve this in Haskell factorial :: Int -> Int factorial 0 = 1 factorial n = n * (factorial (n-1)) Note the bracketing in factorial (n-1) factorial n-1 would be bracketed as (factorial n) -1

Defining functions... Functions are often defined inductively Base case: Explicit value for f (0) Inductive step: Define f (n) in terms of f (n 1),..., f (0) For example, factorial is usually defined inductively 0! = 1 n! = n (n 1)! Use pattern matching to achieve this in Haskell factorial :: Int -> Int factorial 0 = 1 factorial n = n * (factorial (n-1)) Note the bracketing in factorial (n-1) factorial n-1 would be bracketed as (factorial n) -1 No guarantee of termination, correctness! What does factorial (-1) generate?

Conditional definitions Conditional definitions using guards For instance, fix the function to work for negative inputs factorial :: Int -> Int factorial 0 = 1 factorial n n < 0 = factorial (-n) n > 0 = n * (factorial (n-1))

Conditional definitions Conditional definitions using guards For instance, fix the function to work for negative inputs factorial :: Int -> Int factorial 0 = 1 factorial n n < 0 = factorial (-n) n > 0 = n * (factorial (n-1)) Second definition has two parts Each part is guarded by a condition Guards are tested top to bottom

Computation as rewriting Use definitions to simplify expressions till no further simplification is possible

Computation as rewriting Use definitions to simplify expressions till no further simplification is possible Builtin simplifications 3 + 5 8 True False True

Computation as rewriting Use definitions to simplify expressions till no further simplification is possible Builtin simplifications 3 + 5 8 True False True Simplifications based on user defined functions

Computation as rewriting Use definitions to simplify expressions till no further simplification is possible Builtin simplifications 3 + 5 8 True False True Simplifications based on user defined functions power :: Float -> Int -> Float power x 0 = 1.0 power x n n > 0 = x * (power x (n-1))

Computation as rewriting Use definitions to simplify expressions till no further simplification is possible Builtin simplifications 3 + 5 8 True False True Simplifications based on user defined functions power :: Float -> Int -> Float power x 0 = 1.0 power x n n > 0 = x * (power x (n-1)) power 3.0 2 3.0 * (power 3.0 (2-1)) 3.0 * (power 3.0 1) 3.0 * 3.0 * (power 3.0 (1-1)) 3.0 * 3.0 * (power 3.0 0) 3.0 * 3.0 * 1.0 9.0 * 1.0 9.0

Computation as rewriting... More than one expression may qualify for rewriting

Computation as rewriting... More than one expression may qualify for rewriting sqr x = x*x

Computation as rewriting... More than one expression may qualify for rewriting sqr x = x*x sqr (4+3) sqr 7 7*7 49 (4+3)*(4+3) (4+3)*7 7*7 49

Computation as rewriting... More than one expression may qualify for rewriting sqr x = x*x sqr (4+3) sqr 7 7*7 49 (4+3)*(4+3) (4+3)*7 7*7 49 If there are multiple expressions to rewrite, Haskell chooses outermost expression

Computation as rewriting... More than one expression may qualify for rewriting sqr x = x*x sqr (4+3) sqr 7 7*7 49 (4+3)*(4+3) (4+3)*7 7*7 49 If there are multiple expressions to rewrite, Haskell chooses outermost expression Outermost reduction Lazy rewriting Evaluate argument to a function only when needed. Eager rewriting evaluate arguments before evaluating function

Computation as rewriting... Outermost reduction can duplicate subexpressions

Computation as rewriting... Outermost reduction can duplicate subexpressions sqr (4+3) (4+3)*(4+3)

Computation as rewriting... Outermost reduction can duplicate subexpressions sqr (4+3) (4+3)*(4+3) Maintain pointers to identical subexpressions generated by copying at the time of reduction Reduce a duplicated expression only once

Computation as rewriting... Outermost reduction can duplicate subexpressions sqr (4+3) (4+3)*(4+3) Maintain pointers to identical subexpressions generated by copying at the time of reduction Reduce a duplicated expression only once Haskell cannot otherwise detect identical subexpressions diffsquare :: Float -> Float -> Float diffsquare x y = (x - y) * (x - y)

Computation as rewriting... Outermost reduction may terminate when innermost does not

Computation as rewriting... Outermost reduction may terminate when innermost does not power :: Float -> Int -> Float power x 0 = 1.0 power x n n > 0 = x * (power x (n-1)) power (7.0/0.0) 0 1.0

Computation as rewriting... Outermost reduction may terminate when innermost does not power :: Float -> Int -> Float power x 0 = 1.0 power x n n > 0 = x * (power x (n-1)) power (7.0/0.0) 0 1.0 Outermost and innermost reduction give same answer when both terminate Order of evaluation of subexpressions does not matter

Lists Basic collective type in Haskell is a list [1,2,3,1] is a list of Int [True,False,True] is a list of Bool Elements of a list must all be of uniform type Cannot write [1,2,True] or [3.0, a ] List of underlying type T has type [T] [1,2,3,1]::[Int], [True,False,True]::[Bool] Empty list is [] for all types Lists can be nested [[3,2],[],[7,7,7]] is of type [[Int]]

Internal representation on lists Basic list building operator is : Append an element to the left of a list 1:[2,3,4] [1,2,3,4]

Internal representation on lists Basic list building operator is : Append an element to the left of a list 1:[2,3,4] [1,2,3,4] All Haskell lists are built up from [] using operator : [1,2,3,4] is actually 1:(2:(3:(4:[]))) : is right associative, so 1:2:3:4:[] = 1:(2:(3:(4:[])))

Internal representation on lists Basic list building operator is : Append an element to the left of a list 1:[2,3,4] [1,2,3,4] All Haskell lists are built up from [] using operator : [1,2,3,4] is actually 1:(2:(3:(4:[]))) : is right associative, so 1:2:3:4:[] = 1:(2:(3:(4:[]))) Functions head and tail to decompose a list head (x:l) = x tail (x:l) = l Undefined for [] head returns a value, tail returns a list

Defining list functions inductively Inductive definitions Define f for [] Derive f l by combining head l and f (tail l)

Defining list functions inductively Inductive definitions Define f for [] Derive f l by combining head l and f (tail l) length :: [Int] -> Int length [] = 0 length l = 1 + (length (tail l)) sum :: [Int] -> Int sum [] = 0 sum l = (head l) + (sum (tail l))

Functions on lists... Implicitly extract head and tail using pattern matching length :: [Int] -> Int length [] = 0 length (x:xs) = 1 + (length xs) sum :: [Int] -> Int sum [] = 0 sum (x:xs) = x + (sum xs)

Functions on lists... Combine two lists into one append append [3,2] [4,6,7] [3,2,4,6,7] append :: [Int] -> [Int] -> [Int] append [] ys = ys append (x:xs) ys = x:(append xs ys)

Functions on lists... Combine two lists into one append append [3,2] [4,6,7] [3,2,4,6,7] append :: [Int] -> [Int] -> [Int] append [] ys = ys append (x:xs) ys = x:(append xs ys) Builtin operator ++ for append [1,2,3] ++ [4,3] [1,2,3,4,3]

Functions on lists... Combine two lists into one append append [3,2] [4,6,7] [3,2,4,6,7] append :: [Int] -> [Int] -> [Int] append [] ys = ys append (x:xs) ys = x:(append xs ys) Builtin operator ++ for append [1,2,3] ++ [4,3] [1,2,3,4,3] concat dissolves one level of brackets concat [[Int]] -> [Int] concat [] = [] concat (l:ls) = l ++ (concat ls) concat [[1,2],[],[2,1]] [1,2,2,1]

List functions: map String is a synonym for [Char] touppercase applies capitalize to each Char in as String capitalize :: Char -> Char does what its name suggests touppercase :: String -> String touppercase "" = "" touppercase (c:cs) = (capitalize c):(touppercase cs)

List functions: map String is a synonym for [Char] touppercase applies capitalize to each Char in as String capitalize :: Char -> Char does what its name suggests touppercase :: String -> String touppercase "" = "" touppercase (c:cs) = (capitalize c):(touppercase cs) An example of builtin function map map f [x0,x1,..,xk] = [(f x0),(f x1),...,(f xk)] Apply f pointwise to each element in a list

List functions: map String is a synonym for [Char] touppercase applies capitalize to each Char in as String capitalize :: Char -> Char does what its name suggests touppercase :: String -> String touppercase "" = "" touppercase (c:cs) = (capitalize c):(touppercase cs) An example of builtin function map map f [x0,x1,..,xk] = [(f x0),(f x1),...,(f xk)] Apply f pointwise to each element in a list touppercase using map touppercase :: String -> String touppercase s = map capitalize s

List functions: map String is a synonym for [Char] touppercase applies capitalize to each Char in as String capitalize :: Char -> Char does what its name suggests touppercase :: String -> String touppercase "" = "" touppercase (c:cs) = (capitalize c):(touppercase cs) An example of builtin function map map f [x0,x1,..,xk] = [(f x0),(f x1),...,(f xk)] Apply f pointwise to each element in a list touppercase using map touppercase :: String -> String touppercase s = map capitalize s Note that first argument of map is a function! Higher order types

List functions: filter Select items from a list based on a property

List functions: filter Select items from a list based on a property evenonly :: [Int] -> [Int] evenonly [] = [] evenonly (n:ns) mod n 2 == 0 = n:(evenonly ns) otherwise = evenonly ns

List functions: filter Select items from a list based on a property evenonly :: [Int] -> [Int] evenonly [] = [] evenonly (n:ns) mod n 2 == 0 = n:(evenonly ns) otherwise = evenonly ns Same as applying the test iseven :: Int -> Bool iseven n = (mod n 2 == 0) to each element in the list

List functions: filter Select items from a list based on a property evenonly :: [Int] -> [Int] evenonly [] = [] evenonly (n:ns) mod n 2 == 0 = n:(evenonly ns) otherwise = evenonly ns Same as applying the test iseven :: Int -> Bool iseven n = (mod n 2 == 0) to each element in the list filter selects all items from l that satisfy p filter p [] = [] filter p (x:xs) (p x) = x:(filter p xs) otherwise = filter p xs

List functions: filter Select items from a list based on a property evenonly :: [Int] -> [Int] evenonly [] = [] evenonly (n:ns) mod n 2 == 0 = n:(evenonly ns) otherwise = evenonly ns Same as applying the test iseven :: Int -> Bool iseven n = (mod n 2 == 0) to each element in the list filter selects all items from l that satisfy p filter p [] = [] filter p (x:xs) (p x) = x:(filter p xs) otherwise = filter p xs evenonly l = filter iseven l

Polymorphism Functions like length, reverse do not need to examine elements in a list

Polymorphism Functions like length, reverse do not need to examine elements in a list Use a type variable to denote an arbitrary type

Polymorphism Functions like length, reverse do not need to examine elements in a list Use a type variable to denote an arbitrary type length :: [a] -> Int length [] = 0 length (x:xs) = 1 + (length xs)

Polymorphism Functions like length, reverse do not need to examine elements in a list Use a type variable to denote an arbitrary type Similarly length :: [a] -> Int length [] = 0 length (x:xs) = 1 + (length xs) reverse :: [a] -> [a] (++) :: [a] -> [a] -> [a] concat :: [[a]] -> [a]

Polymorphism Functions like length, reverse do not need to examine elements in a list Use a type variable to denote an arbitrary type Similarly length :: [a] -> Int length [] = 0 length (x:xs) = 1 + (length xs) reverse :: [a] -> [a] (++) :: [a] -> [a] -> [a] concat :: [[a]] -> [a] Polymorphism: same computation rule for multiple types

Polymorphism Functions like length, reverse do not need to examine elements in a list Use a type variable to denote an arbitrary type Similarly length :: [a] -> Int length [] = 0 length (x:xs) = 1 + (length xs) reverse :: [a] -> [a] (++) :: [a] -> [a] -> [a] concat :: [[a]] -> [a] Polymorphism: same computation rule for multiple types Overloading: same abstract operation but implementation varies Representations of Int and Float are different so + and * are implemented differently

Polymorphism: map and filter What is the type of map? map f [x0,x1,..,xk] = [(f x0),(f x1),...,(f xk)] Most general type for f is a->b Input list is fed to f, so type is [a] Output is list of items generated by f, so type is [b]

Polymorphism: map and filter What is the type of map? map f [x0,x1,..,xk] = [(f x0),(f x1),...,(f xk)] Most general type for f is a->b Input list is fed to f, so type is [a] Output is list of items generated by f, so type is [b] map : (a -> b) -> [a] -> [b]

Polymorphism: map and filter What is the type of map? map f [x0,x1,..,xk] = [(f x0),(f x1),...,(f xk)] Most general type for f is a->b Input list is fed to f, so type is [a] Output is list of items generated by f, so type is [b] map : (a -> b) -> [a] -> [b] What is the type of filter

Polymorphism: map and filter What is the type of map? map f [x0,x1,..,xk] = [(f x0),(f x1),...,(f xk)] Most general type for f is a->b Input list is fed to f, so type is [a] Output is list of items generated by f, so type is [b] map : (a -> b) -> [a] -> [b] What is the type of filter filter p [] = [] filter p (x:xs) (p x) = x:(filter p xs) otherwise = filter p xs

Polymorphism: map and filter What is the type of map? map f [x0,x1,..,xk] = [(f x0),(f x1),...,(f xk)] Most general type for f is a->b Input list is fed to f, so type is [a] Output is list of items generated by f, so type is [b] map : (a -> b) -> [a] -> [b] What is the type of filter filter p [] = [] filter p (x:xs) (p x) = x:(filter p xs) otherwise = filter p xs filter : (a -> Bool) -> [a] -> [a]

Summary Haskell: a notation for defining computable functions Currying to deal with functions of different arities Computation is rewriting Haskell uses outermost reduction Order of evaluation does not change the answer (if an answer is produced!) Higher order types Can pass functions as arguments Polymorphism Same rule works for multiple types