a third look at ml

61
A Third Look At ML A Third Look At ML Chapter Nine Modern Programming Languages 1

Upload: nguyet

Post on 13-Jan-2016

25 views

Category:

Documents


0 download

DESCRIPTION

A Third Look At ML. Outline. More pattern matching Function values and anonymous functions Higher-order functions and currying Predefined higher-order functions. More Pattern-Matching. Last time we saw pattern-matching in function definitions: fun f 0 = "zero" | f _ = "non-zero"; - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: A Third Look At ML

A Third Look At MLA Third Look At ML

Chapter Nine Modern Programming Languages 1

Page 2: A Third Look At ML

OutlineOutlineMore pattern matchingFunction values and anonymous

functionsHigher-order functions and

curryingPredefined higher-order functions

Chapter Nine Modern Programming Languages 2

Page 3: A Third Look At ML

More Pattern-MatchingMore Pattern-MatchingLast time we saw pattern-

matching in function definitions:◦ fun f 0 = "zero"| f _ = "non-zero";

Pattern-matching occurs in several other kinds of ML expressions:◦ case n of 0 => "zero" | _ => "non-zero";

Chapter Nine Modern Programming Languages 3

Page 4: A Third Look At ML

Match SyntaxMatch SyntaxA rule is a piece of ML syntax that looks

like this:

A match consists of one or more rules separated by a vertical bar, like this:

Each rule in a match must have the same type of expression on the right-hand side

A match is not an expression by itself, but forms a part of several kinds of ML expressions

Chapter Nine Modern Programming Languages 4

<rule> ::= <pattern> => <expression>

<match> ::= <rule> | <rule> '|' <match>

Page 5: A Third Look At ML

Case ExpressionsCase Expressions

The syntax is

This is a very powerful case construct—unlike many languages, it does more than just compare with constants

Chapter Nine Modern Programming Languages 5

- case 1+1 of= 3 => "three" |= 2 => "two" |= _ => "hmm";val it = "two" : string

<case-expr> ::= case <expression> of <match>

Page 6: A Third Look At ML

ExampleExample

Chapter Nine Modern Programming Languages 6

case x of _::_::c::_ => c | _::b::_ => b | a::_ => a | nil => 0

The value of this expression is the third elementof the list x, if it has at least three, or the second element if x has only two, or the first element if x has only one, or 0 if x is empty.

Page 7: A Third Look At ML

Generalizes Generalizes ifif

The two expressions above are equivalent

So if-then-else is really just a special case of case

Chapter Nine Modern Programming Languages 7

if exp1 then exp2 else exp3

case exp1 of true => exp2 | false => exp3

Page 8: A Third Look At ML

Behind the ScenesBehind the ScenesExpressions using if are actually

treated as abbreviations for case expressions

This explains some odd SML/NJ error messages:

Chapter Nine Modern Programming Languages 8

- if 1=1 then 1 else 1.0;Error: types of rules don't agree [literal] earlier rule(s): bool -> int this rule: bool -> real in rule: false => 1.0

Page 9: A Third Look At ML

OutlineOutlineMore pattern matchingFunction values and anonymous

functionsHigher-order functions and

curryingPredefined higher-order functions

Chapter Nine Modern Programming Languages 9

Page 10: A Third Look At ML

Predefined FunctionsPredefined Functions

When an ML language system starts, there are many predefined variables

Some are bound to functions:

Chapter Nine Modern Programming Languages 10

- ord;val it = fn : char -> int- ~;val it = fn : int -> int

Page 11: A Third Look At ML

Defining FunctionsDefining Functions

We have seen the fun notation for defining new named functions

You can also define new names for old functions, using val just as for other kinds of values:

Chapter Nine Modern Programming Languages 11

- val x = ~;val x = fn : int -> int- x 3;val it = ~3 : int

Page 12: A Third Look At ML

Function ValuesFunction ValuesFunctions in ML do not have

namesJust like other kinds of values,

function values bound to one or more variables

The fun syntax does two separate things:◦Creates a new function entity◦Binds that function entity to a name

Chapter Nine Modern Programming Languages 12

Page 13: A Third Look At ML

Anonymous FunctionsAnonymous FunctionsNamed function:

Anonymous function:

Chapter Nine Modern Programming Languages 13

- fun f x = x + 2;val f = fn : int -> int- f 1;val it = 3 : int

- fn x => x + 2;val it = fn : int -> int- (fn x => x + 2) 1;val it = 3 : int

Page 14: A Third Look At ML

The The fnfn Syntax SyntaxAnother use of the match syntax

Using fn, we get an expression whose value is an (anonymous) function

We can define what fun does in terms of val and fn

These two definitions have the same effect:◦ fun f x = x + 2◦ val f = fn x => x + 2

Chapter Nine Modern Programming Languages 14

<fun-expr> ::= fn <match>

a match

Page 15: A Third Look At ML

fnfn and and recrecA special syntax is required for binding

variables to recursive functions with fn◦ Since the expression is evaluated before

binding, and the function has no name, you can’t recurse directly

The rec keyword allows you to accomplish this

- val rec fact = fn 0 => 1 | n => n*fact(n-1);val fact = fn : int -> int

Chapter Nine Modern Programming Languages 15

Page 16: A Third Look At ML

Using Anonymous Using Anonymous FunctionsFunctionsOne simple application: when you

need a small function in just one place

Without fn:

With fn:

Chapter Nine Modern Programming Languages 16

- fun intBefore (a,b) = a < b;val intBefore = fn : int * int -> bool- quicksort ([1,4,3,2,5], intBefore);val it = [1,2,3,4,5] : int list

- quicksort ([1,4,3,2,5], fn (a,b) => a<b);val it = [1,2,3,4,5] : int list- quicksort ([1,4,3,2,5], fn (a,b) => a>b);val it = [5,4,3,2,1] : int list

Page 17: A Third Look At ML

The The opop keyword keyword

Binary operators are special functionsSometimes you want to treat them

like plain functions: to pass <, for example, as an argument of type int * int -> bool

The keyword op before an operator gives you the underlying function

Chapter Nine Modern Programming Languages 17

- op *;val it = fn : int * int -> int- quicksort ([1,4,3,2,5], op <);val it = [1,2,3,4,5] : int list

Page 18: A Third Look At ML

Defining Binary Infix Defining Binary Infix ““OperatorsOperators””You can define functions that use

infix notation:◦x f y

Use the infix statement:◦infix [precedence: 0,3-7] <fun-

name>Define with infix syntax:

◦fun x f y = …

Chapter Nine Modern Programming Languages 18

Page 19: A Third Look At ML

Defining an Infix Defining an Infix plusplus FunctionFunction

Chapter Nine Modern Programming Languages 19

- infix 6 plus;infix 6 plus- fun x plus y = x + y;val plus = fn : int * int -> int- 2 plus 3;val it = 5 : int- val g = op plus;val g = fn : int * int -> int- g (2,3);val it = 5 : int

Page 20: A Third Look At ML

Operator PrecedenceOperator Precedence7: * / div mod6: + - ^5: :: @4: = <> < > <= >=Don’t worry about the others

Chapter Nine Modern Programming Languages 20

Page 21: A Third Look At ML

fnfn vs. vs. casecase

Chapter Nine Modern Programming Languages 21

The notation

case exp of pat1 => exp1 | ... | patn => expn

is shorthand for the function application

(fn pat1 => exp1 | ... | patn => expn) exp

Page 22: A Third Look At ML

Function Objects in C++Function Objects in C++

Chapter Nine Modern Programming Languages 22

Page 23: A Third Look At ML

Anonymous Functions in Anonymous Functions in C++0xC++0x

Chapter Nine Modern Programming Languages 23

Page 24: A Third Look At ML

OutlineOutlineMore pattern matchingFunction values and anonymous

functionsHigher-order functions and

curryingPredefined higher-order functions

Chapter Nine Modern Programming Languages 24

Page 25: A Third Look At ML

Higher-order FunctionsHigher-order FunctionsEvery function has an order:

◦A function that does not take any functions as parameters, and does not return a function value, has order 1

◦A function that takes a function as a parameter or returns a function value has order n+1, where n is the order of its highest-order function parameter or returned value

The quicksort we just saw is a second-order function

Chapter Nine Modern Programming Languages 25

Page 26: A Third Look At ML

PracticePractice

Chapter Nine Modern Programming Languages 26

What is the order of functions with each of the following ML types?

int * int -> boolint list * (int * int -> bool) -> int listint -> int -> int(int -> int) * (int -> int) -> (int -> int)int -> bool -> real -> string

What can you say about the order of a function with this type?

('a -> 'b) * ('c -> 'a) -> 'c -> 'b

Page 27: A Third Look At ML

CurryingCurryingWe've seen how to get two

parameters into a function by passing a 2-tuple:

fun f (a,b) = a + b;

Another way is to write a function that takes the first argument, and returns another function that takes the second argument:

fun g a = fn b => a+b;

The general name for this is currying◦Arguments are supplied in successive

callsChapter Nine Modern Programming Languages 27

Page 28: A Third Look At ML

Curried AdditionCurried Addition

Remember that function application is left-associative

So g 2 3 means ((g 2) 3)

Chapter Nine Modern Programming Languages 28

- fun f (a,b) = a+b; (* not curried *)val f = fn : int * int -> int- fun g a = fn b => a+b; (* curried *)val g = fn : int -> int -> int- f(2,3);val it = 5 : int- g 2 3;val it = 5 : int

Page 29: A Third Look At ML

AdvantagesAdvantagesNo tuples: we get to write g 2 3 instead of f(2,3)

But the real advantage: we get to specialize functions for particular initial parameters

Chapter Nine Modern Programming Languages 29

- val add2 = g 2;val add2 = fn : int -> int- add2 3;val it = 5 : int- add2 10;val it = 12 : int

Page 30: A Third Look At ML

Advantages: ExampleAdvantages: ExampleLike the previous quicksortBut now, the comparison function

is the first, curried parameter

Chapter Nine Modern Programming Languages 30

- quicksort (op <) [1,4,3,2,5];val it = [1,2,3,4,5] : int list- val sortBackward = quicksort (op >);val sortBackward = fn : int list -> int list- sortBackward [1,4,3,2,5];val it = [5,4,3,2,1] : int list

Page 31: A Third Look At ML

Multiple Curried Multiple Curried ParametersParametersCurrying generalizes to any

number of parameters

Chapter Nine Modern Programming Languages 31

- fun f (a,b,c) = a+b+c;val f = fn : int * int * int -> int- fun g a = fn b => fn c => a+b+c;val g = fn : int -> int -> int -> int- f (1,2,3);val it = 6 : int- g 1 2 3;val it = 6 : int

Page 32: A Third Look At ML

Notation For CurryingNotation For CurryingThere is a much simpler notation for

currying (on the next slide)The long notation we have used so far

makes the little intermediate anonymous functions explicit:

But as long as you understand how it works, the simpler notation is much easier to read and write…

Chapter Nine Modern Programming Languages 32

fun g a = fn b => fn c => a+b+c;

Page 33: A Third Look At ML

Easier Notation for Easier Notation for CurryingCurrying

Instead of writing:fun f a = fn b => a+b;

We can just write:fun f a b = a+b;

This generalizes for any number of curried arguments

Chapter Nine Modern Programming Languages 33

- fun f a b c d = a+b+c+d;val f = fn : int -> int -> int -> int -> int

Page 34: A Third Look At ML

std::bind in C++0xstd::bind in C++0x

Chapter Nine Modern Programming Languages 34

Page 35: A Third Look At ML

Function CompositionFunction CompositionUsed frequently in mathematics

and functional programmingDefine a new function as a

sequential application of one or more other functions:◦h(x) = f(g(x))◦Can be written h = f ੦ g◦ML uses the letter ‘o’

g ’s output type must be f ’s input type

Chapter Nine Modern Programming Languages 35

Page 36: A Third Look At ML

Function CompositionFunction CompositionExample 1Example 1

Chapter Nine Modern Programming Languages 36

- fun f x = x + 2;val f = fn : int -> int- fun g x = 3 * x;val g = fn : int -> int- fun h x = f (g x);val h = fn : int -> int- f (g 5); val it = 17 : int- h 5;val it = 17 : int

Page 37: A Third Look At ML

Function CompositionFunction CompositionExample 2Example 2

Chapter Nine Modern Programming Languages 37

- f o g;val it = fn : int -> int-val h = f o g; (* or fun h x = (f o g) x; *) val h = fn : int -> int- h 5;val it = 17 : int

Page 38: A Third Look At ML

Function CompositionFunction CompositionExample 3Example 3

Chapter Nine Modern Programming Languages 38

- map;val it = fn : ('a -> 'b) -> 'a list -> 'b list- map ord;val it = fn : char list -> int list- explode;val it = fn : string -> char list- val a = map ord o explode;val a = fn : string -> int list- a "hello";val it = [104,101,108,108,111] : int list

Page 39: A Third Look At ML

Strange BehaviorStrange Behavior

Chapter Nine Modern Programming Languages 39

- hd;val it = fn : 'a list -> 'a- tl;val it = fn : 'a list -> 'a list- hd o tl;stdIn:32.1-32.8 Warning: type vars not generalized because of value restriction are instantiated to dummy types (X1,X2,...)val it = fn : ?.X1 list -> ?.X1

Page 40: A Third Look At ML

MLML’’s Value Restrictions Value RestrictionA “dark corner”

◦Has to do with making imperative programming as safe as possible in ML

Expressions at the “top level” must be one of the following:◦values (no further evaluation pending)

5 is a value; 2+3 is not

◦monomorphic (no type variables)See next slide

Chapter Nine Modern Programming Languages 40

Page 41: A Third Look At ML

Value Restriction Value Restriction WorkaroundWorkaround

Chapter Nine Modern Programming Languages 41

- val f = map length;stdIn:18.5-18.19 Warning: type vars not generalized because of value restriction are instantiated to dummy types (X1,X2,...)val f = fn : ?.X1 list list -> int list- fun f x = map length x; (*In f: not at top-level *)val f = fn : 'a list list -> int list- f [[1,2],[3,4,5]];val it = [2,3] : int list- f nil;val it = [] : int list

Page 42: A Third Look At ML

OutlineOutlineMore pattern matchingFunction values and anonymous

functionsHigher-order functions and

curryingPredefined higher-order functions

Chapter Nine Modern Programming Languages 42

Page 43: A Third Look At ML

Predefined Higher-Order Predefined Higher-Order FunctionsFunctionsWe will use three important

predefined higher-order functions:◦ map◦ foldr◦ foldl

Actually, foldr and foldl are very similar, as you might guess from the names

Chapter Nine Modern Programming Languages 43

Page 44: A Third Look At ML

The The mapmap Function Function

Used to apply a function to every element of a list, and collect a list of results

Chapter Nine Modern Programming Languages 44

- map ~ [1,2,3,4];val it = [~1,~2,~3,~4] : int list- map (fn x => x+1) [1,2,3,4];val it = [2,3,4,5] : int list- map (fn x => x mod 2 = 0) [1,2,3,4];val it = [false,true,false,true] : bool list- map (op +) [(1,2),(3,4),(5,6)];val it = [3,7,11] : int list

Page 45: A Third Look At ML

The The mapmap Function Is Function Is CurriedCurried

Chapter Nine Modern Programming Languages 45

- map;val it = fn : ('a -> 'b) -> 'a list -> 'b list- val f = map (op +);val f = fn : (int * int) list -> int list- f [(1,2),(3,4)];val it = [3,7] : int list

Page 46: A Third Look At ML

Implementing Implementing mapmap

Chapter Nine Modern Programming Languages 46

- fun map f nil = nil

= | map f (x::xs) = f x :: map f xs;

val map = fn : ('a -> 'b) -> 'a list -> 'b list

- map (op ~) [1,2,3];

val it = [~1,~2,~3] : int list

Page 47: A Third Look At ML

Implementing Implementing mapmapTake 2Take 2

Chapter Nine Modern Programming Languages 47

- fun map f nil = nil

= | map f (x::xs) = (op ::)(f x, map f xs);

val map = fn : ('a -> 'b) -> 'a list -> 'b list

- map (op ~) [1,2,3];

val it = [~1,~2,~3] : int list

Page 48: A Third Look At ML

A Common PatternA Common PatternConsider adding list elements:fun sum nil = 0| sum (h::t) = (op +)(h,sum t);computes x1 + (x2 + (x3 +… (xn + 0)…))

Or multiplying them:fun mult nil = 1| mult(h::t) = (op * )(h,mult t);computes x1 * (x2 * (x3 *… (xn * 1)…))

The pattern:fun newf nil = c| newf(h::t) = f(h,newf t);computes f(x1,f(x2,f(x3,… f(xn,c)…))

Chapter Nine Modern Programming Languages 48

Page 49: A Third Look At ML

Capturing the PatternCapturing the PatternSee reduce.smlSee reduce.sml

Make the accumulating function (f) and the initial value (c) parameters to a higher-order function

We’ll call the generic function reduce:

fun reduce _ c nil = c

| reduce f c (h::t) = f(h, reduce f c t);

Chapter Nine Modern Programming Languages 49

Page 50: A Third Look At ML

What What reducereduce Computes ComputesA DerivationA Derivation

Then reduce f c [x1,x2,…,xn] =f(x1,reduce f c [x2,…,xn]) =f(x1,f(x2,reduce f c [x3,…,xn])) … =f(x1,f(x2, …f(xn,reduce f c nil) …))

f(x1,f(x2, …f(xn,c) …))Note that this evaluates inside-out

◦So the last list element is processed first◦And the “first shall be last” :-)

See also: reduce.py

Chapter Nine Modern Programming Languages 50

Page 51: A Third Look At ML

Using Using reducereduce to Create to Create FunctionsFunctionsval sum = reduce (op +) 0;

val mult = reduce (op * ) 1;

val anytrue =reduce (fn (x,r) => x orelse r) false;

val alltrue =reduce (fn (x,r) => x andalso r) true;

fun append a b = reduce (op ::) b a;

Chapter Nine Modern Programming Languages 51

Page 52: A Third Look At ML

Implementing Implementing mapmap with with reducereduce

fun map f =reduce (fn (x, sofar) => (f x)::sofar) nil;

Chapter Nine Modern Programming Languages 52

Page 53: A Third Look At ML

The The foldrfoldr Function FunctionIn ML In ML reducereduce is called is called foldrfoldr

Chapter Nine Modern Programming Languages 53

- foldr (op ^) "" ["abc","def","ghi"];val it = "abcdefghi" : string- foldr (op ::) [5] [1,2,3,4];val it = [1,2,3,4,5] : int list

Page 54: A Third Look At ML

Zipping ListsZipping ListsSuppose you have a pair of

compatible lists◦same type and length◦you can “zip them”

fun zip (nil,nil) = nil

| zip (x::xs, y::ys) = (x,y)::zip (xs,ys);- zip ([1,2],[3,4]);

val it = [(1,3),(2,4)] : (int * int) list

Chapter Nine Modern Programming Languages 54

Page 55: A Third Look At ML

Unzipping ListsUnzipping Lists

Chapter Nine Modern Programming Languages 55

fun unzip nil = (nil,nil)| unzip ((x,y)::rest) = let val (xs,ys) = unzip rest in (x::xs, y::ys) end;

- unzip [(1,3),(2,4)];val it = ([1,2],[3,4]) : int list * int list

How would you write unzip with foldr?

Page 56: A Third Look At ML

The The foldlfoldl Function Function

Used to combine all the elements of a list, left-to-rightSame results as foldr in some cases

Chapter Nine Modern Programming Languages 56

- foldl (op +) 0 [1,2,3,4];val it = 10 : int- foldl (op * ) 1 [1,2,3,4];val it = 24 : int

Page 57: A Third Look At ML

The The foldlfoldl Function Function

It takes a function f, a starting value c, and a list x = [x1, …, xn] and computes:

So foldl (op +) 0 [1,2,3,4] evaluates as 4+(3+(2+(1+0)))=10

Remember, foldr did 1+(2+(3+(4+0)))=10

Chapter Nine Modern Programming Languages 57

cxfxfxfxf nn ,,,, 121

Page 58: A Third Look At ML

The The foldlfoldl Function Functionfoldl starts at the left, foldr starts at the right

Difference does not matter when the function is commutative, like + and *

For other operations, it does matter

Chapter Nine Modern Programming Languages 58

- foldr (op ^) "" ["abc","def","ghi"];val it = "abcdefghi" : string- foldl (op ^) "" ["abc","def","ghi"];val it = "ghidefabc" : string- foldr (op -) 0 [1,2,3,4];val it = ~2 : int- foldl (op -) 0 [1,2,3,4];val it = 2 : int

Page 59: A Third Look At ML

std::accumulate in C++std::accumulate in C++

Chapter Nine Modern Programming Languages 59

Page 60: A Third Look At ML

QueryQueryWhat happens if you replace foldr with foldl in the definition of unzip?

How about append?How would you write reverse

using foldl?

Chapter Nine Modern Programming Languages 60

Page 61: A Third Look At ML

““FunFun”” for the Enterprising for the Enterprising StudentStudentReview remove.smlWrite functions using that

remove:◦all occurrences of a value from a list◦all duplicates◦curried and non-curried versions

Chapter Nine Modern Programming Languages 61