poly-ho!poly-ho! polymorphic, higher-order programming cos 326 david walker princeton university...

67
Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse these slides for non-commercial educaJonal purposes

Upload: others

Post on 13-Oct-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Poly-HO!

polymorphic,higher-orderprogramming

COS326DavidWalker

PrincetonUniversityslidescopyright2013-2015DavidWalkerandAndrewW.Appel

permissiongrantedtoreusetheseslidesfornon-commercialeducaJonalpurposes

Page 2: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

SomeDesign&CodingRules

2

Page 3: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

SomeDesign&CodingRules

3

•  Lazinesscanbeareallygoodforceindesign.•  Neverwritethesamecodetwice.

–  factoroutthecommonbitsintoareusableprocedure.–  beOer,usesomeoneelse’s(well-tested,well-documented,andwell-maintained)procedure.

•  Whyisthisagoodidea?–  whydon’twejustcut-and-pastesnippetsofcodeusingtheeditorinsteadofabstracJngthemintoprocedures?

Page 4: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

SomeDesign&CodingRules

4

•  Lazinesscanbeareallygoodforceindesign.•  Neverwritethesamecodetwice.

–  factoroutthecommonbitsintoareusableprocedure.–  beOer,usesomeoneelse’s(well-tested,well-documented,andwell-maintained)procedure.

•  Whyisthisagoodidea?–  whydon’twejustcut-and-pastesnippetsofcodeusingtheeditorinsteadofabstracJngthemintoprocedures?

–  findandfixabuginonecopy,havetofixinallofthem.–  decidetochangethefuncJonality,havetotrackdownalloftheplaceswhereitgetsused.

Page 5: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

FactoringCodeinOCaml

5

ConsiderthesedefiniJons:

let rec inc_all (xs:int list) : int list = match xs with | [] -> [] | hd::tl -> (hd+1)::(inc_all tl) let rec square_all (xs:int list) : int list = match xs with | [] -> [] | hd::tl -> (hd*hd)::(square_all tl)

Page 6: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

FactoringCodeinOCaml

6

ConsiderthesedefiniJons:ThecodeisalmostidenJcal–factoritout!

let rec inc_all (xs:int list) : int list = match xs with | [] -> [] | hd::tl -> (hd+1)::(inc_all tl) let rec square_all (xs:int list) : int list = match xs with | [] -> [] | hd::tl -> (hd*hd)::(square_all tl)

Page 7: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

FactoringCodeinOCaml

7

Ahigher-orderfuncJoncapturestherecursionpaOern:

let rec map (f:int->int) (xs:int list) : int list = match xs with | [] -> [] | hd::tl -> (f hd)::(map f tl);;

Page 8: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

FactoringCodeinOCaml

8

Ahigher-orderfuncJoncapturestherecursionpaOern:UsesofthefuncJon:

let rec map (f:int->int) (xs:int list) : int list = match xs with | [] -> [] | hd::tl -> (f hd)::(map f tl);;

let inc x = x+1;; let inc_all xs = map inc xs;;

Page 9: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

FactoringCodeinOCaml

9

Ahigher-orderfuncJoncapturestherecursionpaOern:UsesofthefuncJon:

let rec map (f:int->int) (xs:int list) : int list = match xs with | [] -> [] | hd::tl -> (f hd)::(map f tl);;

let inc x = x+1;; let inc_all xs = map inc xs;; let square y = y*y;; let square_all xs = map square xs;;

WriJngliOlefuncJonslikeincjustsowecallmapisapain.

Page 10: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

FactoringCodeinOCaml

10

Ahigher-orderfuncJoncapturestherecursionpaOern:UsesofthefuncJon:

let rec map (f:int->int) (xs:int list) : int list = match xs with | [] -> [] | hd::tl -> (f hd)::(map f tl);;

let inc_all xs = map (fun x -> x + 1) xs;; let square_all xs = map (fun y -> y * y) xs;;

WecanuseananonymousfuncJoninstead. Originally,

ChurchwrotethisfuncJon

usingλ insteadoffun:

(λx.x+1)or(λx.x*x)

Page 11: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Anotherexample

11

let rec sum (xs:int list) : int = match xs with | [] -> 0 | hd::tl -> hd + (sum tl) ;; let rec prod (xs:int list) : int = match xs with | [] -> 1 | hd::tl -> hd * (prod tl) ;; Goal:CreateafuncJoncalledreducethat

whensuppliedwithafewargumentscanimplementbothsumandprod.Definesum2andprod2usingreduce.(Tryit)

Goal:Ifyoufinishearly,usemapandreducetogethertofindthesumofthesquaresoftheelementsofalist.(Tryit)

Page 12: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Agenericreducer

12

let add x y = x + y;; let mul x y = x * y;; let rec reduce (f:int->int->int) (u:int) (xs:int list) : int = match xs with | [] -> u | hd::tl -> f hd (reduce f u tl);; let sum xs = reduce add 0 xs ;; let prod xs = reduce mul 1 xs ;;

Page 13: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

UsingAnonymousFuncJons

13

let rec reduce (f:int->int->int) (u:int) (xs:int list) : int = match xs with | [] -> u | hd::tl -> f hd (reduce f u tl);; let sum xs = reduce (fun x y -> x+y) 0 xs ;; let prod xs = reduce (fun x y -> x*y) 1 xs ;;

Page 14: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

UsingAnonymousFuncJons

14

let rec reduce (f:int->int->int) (u:int) (xs:int list) : int = match xs with | [] -> u | hd::tl -> f hd (reduce f u tl);; let sum xs = reduce (fun x y -> x+y) 0 xs ;; let prod xs = reduce (fun x y -> x*y) 1 xs ;; let sum_of_squares xs = sum (map (fun x -> x * x) xs) let pairify xs = map (fun x -> (x,x)) xs

Page 15: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

MoreonAnonymousFuncJons

15

(nonrecursive)FuncJondeclaraJonsareactuallyabbreviaJons:aresyntac6csugarfor:So,func6onsarevalueswecanbindtoavariable,justlike3or“moo”ortrue.OCamlobeystheprincipleoforthogonallanguagedesign.

let square x = x*x ;; let add x y = x+y ;;

let square = (fun x -> x*x) ;; let add = (fun x y -> x+y) ;;

Page 16: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Oneargument,oneresult

16

Simplifyingfurther:isshorthandfor:Thatis,addisafuncJonwhich:

–  whengivenavaluex,returnsafunc6on(funy->x+y)which:•  whengivenavaluey,returnsx+y.

let add = (fun x y -> x+y)

let add = (fun x -> (fun y -> x+y))

Page 17: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

CurriedFuncJons

17

fun x -> (fun y -> x+y) (* curried *) fun x y -> x + y (* curried *) fun (x,y) -> x+y (* uncurried *) Currying:encodingamulJ-argument

funcJonusingnested,higher-orderfuncJons.

NamedagerthelogicianHaskellB.Curry(1950s).

–  wastryingtofindminimallogicsthatarepowerfulenoughtoencodetradiJonallogics.

–  mucheasiertoprovesomethingaboutalogicwith3connecJvesthanonewith20.

–  theideastranslatedirectlytomath(set&categorytheory)aswellastocomputerscience.

–  (actually,MosesSchönfinkeldidsomeofthisin1924)–  (thankfully,wedon'thavetotalkaboutSchönfinkelledfuncJons)

Page 18: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Whatisthetypeofadd?

18

Add’stypeis:whichwecanwriteas:Thatis,thearrowtypeisright-associaJve.

let add = (fun x -> (fun y -> x+y))

int -> (int -> int)

int -> int -> int

Page 19: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

What’ssogoodaboutCurrying?

19

InaddiJontosimplifyingthelanguage(orthogonaldesign),curryingfuncJonssothattheyonlytakeoneargumentleadstotwomajorwins:

1.  Wecanpar6allyapplyafuncJon.2.  WecanmoreeasilycomposefuncJons.

Page 20: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

ParJalApplicaJon

20

CurriedfuncJonsallowdefsofnew,parJallyappliedfuncJons:EquivalenttowriJng:whichisequivalenttowriJng:also:

let add = (fun x -> (fun y -> x+y)) ;;

let inc = add 1;;

let inc = (fun y -> 1+y);;

let inc y = 1+y;;

let inc2 = add 2;; let inc3 = add 3;;

Page 21: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

SIMPLEREASONINGABOUTHIGHER-ORDERFUNCTIONS

Page 22: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

ReasoningAboutDefiniJons

22

let rec map f xs = match xs with | [] -> [] | hd::tl -> (f hd)::(map f tl);; let square_all = map square;;

let square_all ys = match ys with | [] -> [] | hd::tl -> (square hd)::(square_all tl) ;;

Wecanfactorthisprogram

intothisprogram:

amoreconciseandreadabledefiniJonofsquare_all(assumingwealreadyhaddefinedmap)

Page 23: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

ReasoningAboutDefiniJons

23

Goal:RewritedefiniJonssomyprogramissimpler,easiertounderstand,moreconcise,…Ques6on:WhatarethereasoningprinciplesforrewriJngprogramswithoutbreakingthem?Forreasoningaboutthebehaviorofprograms?Abouttheequivalenceoftwoprograms?Iwantsomerulesfordoingsothatneverfail.

let square_all = map square;;

let square_all ys = match ys with | [] -> [] | hd::tl -> (square hd)::(square_all tl) ;;

Page 24: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

SimpleEquaJonalReasoning

(fun x -> ... x ...) arg ... arg ...

let f = def let f x = (def) x

chosenamexwiselysoitdoesnotshadowothernamesusedindef

ifargisavalueor,whenexecuted,willalwaysterminatewithouteffectandproduceavalue

Rewrite2(SubsJtuJon):

Rewrite3(Eta-expansion):

iffhasafuncJontype

let f x = body let f = (fun x -> body)

Rewrite1(FuncJonde-sugaring):

==

==

==

roughly:alloccurrencesofxreplacedbyarg(thoughgeongthisexactlyrightisshockinglydifficult)

Page 25: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Eta-expansionisanexampleofLeibniz’slaw

let f = def let f = fun x -> (def)x

chosenamexwiselysoitdoesnotshadowothernamesusedindef

Rewrite3(Eta-expansion):

iffhasafuncJontype

==

GotriedWilhelmvonLeibnizGermanPhilosopher1646-1716

Leibniz’slaw:Ifeverypredicatepossessedbyxisalsopossessedbyyandviceversa,thenenJJesxandyareidenJcal.Frequentlyinvokedinmodernlogicandphilosophy.

Page 26: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

EliminaJngtheSugarinMap

26

let rec map f xs = match xs with | [] -> []

| hd::tl -> (f hd)::(map f tl);;

Page 27: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

EliminaJngtheSugarinMap

27

let rec map f xs = match xs with | [] -> []

| hd::tl -> (f hd)::(map f tl);;

let rec map = (fun f -> (fun xs -> match xs with | [] -> [] | hd::tl -> (f hd)::(map f tl)));;

Page 28: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Considersquare_all

28

let rec map = (fun f -> (fun xs -> match xs with | [] -> [] | hd::tl -> (f hd)::(map f tl)));;

let square_all = map square ;;

Page 29: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

SubsJtutemapdefiniJonintosquare_all

29

let rec map = (fun f -> (fun xs -> match xs with | [] -> [] | hd::tl -> (f hd)::(map f tl)));;

let square_all = (fun f ->

(fun xs ->

match xs with | [] -> [] | hd::tl -> (f hd)::(map f tl)

)

) square ;;

Page 30: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

SubsJtutemapdefiniJonintosquare_all

30

let rec map = (fun f -> (fun xs -> match xs with | [] -> [] | hd::tl -> (f hd)::(map f tl)));;

let square_all = (fun f ->

(fun xs ->

match xs with | [] -> [] | hd::tl -> (f hd)::(map f tl)

)

) square ;;

Page 31: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

SubsJtutemapdefiniJonintosquare_all

31

let rec map = (fun f -> (fun xs -> match xs with | [] -> [] | hd::tl -> (f hd)::(map f tl)));;

let square_all = (fun f ->

(fun xs ->

match xs with | [] -> [] | hd::tl -> (f hd)::(map f tl)

)

) square ;;

Page 32: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

SubsJtuteSquare

32

let rec map = (fun f -> (fun xs -> match xs with | [] -> [] | hd::tl -> (f hd)::(map f tl)));;

let square_all = (

(fun xs ->

match xs with | [] -> [] | hd::tl -> (square hd)::(map square tl)

)

;;

argumentsquaresubsJtutedforparameterf

Page 33: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Expandingmapsquare

33

let rec map = (fun f -> (fun xs -> match xs with | [] -> [] | hd::tl -> (f hd)::(map f tl)));;

let square_all ys =

(fun xs ->

match xs with | [] -> [] | hd::tl -> (square hd)::(map square tl)

) ys

;;

addargumentviaeta-expansion

Page 34: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Expandingmapsquare

34

let rec map = (fun f -> (fun xs -> match xs with | [] -> [] | hd::tl -> (f hd)::(map f tl)));;

let square_all ys =

match ys with | [] -> [] | hd::tl -> (square hd)::(map square tl)

;;

subsJtuteagain(argumentysforparameterxs)

Page 35: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

SoFar

35

let rec map f xs = match xs with | [] -> [] | hd::tl -> (f hd)::(map f tl);;

let square_all xs = map square xs

let square_all ys = match ys with | [] -> [] | hd::tl -> (square hd)::(map square tl) ;;

proofbysimplerewriJngunrollsdefiniJononce

Page 36: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

NextStep

36

let rec map f xs = match xs with | [] -> [] | hd::tl -> (f hd)::(map f tl);;

let square_all xs = map square xs

let square_all ys = match ys with | [] -> [] | hd::tl -> (square hd)::(map square tl) ;;

let square_all ys = match ys with | [] -> [] | hd::tl -> (square hd)::(square_all tl) ;;

let square_all ys = match ys with | [] -> [] | hd::tl -> (square hd)::(map square tl) ;;

proofbyinduc6oneliminatesrecursivefuncJonmap

proofbysimplerewriJngunrollsdefiniJononce

Page 37: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Summary

37

Wesawthis:Isequivalenttothis:Moralofthestory•  (1)OCaml’sHOT(higher-order,typed)funcJonscapturerecursionpaOerns•  (2)wecanfigureoutwhatisgoingonbyequa6onalreasoning.•  (3)...butwetypicallyneedtodoproofsbyinduc6ontoreasonabout

recursive(inducJve)funcJons

let rec map f xs = match xs with | [] -> [] | hd::tl -> (f hd)::(map f tl);;

let square_all ys = map square

let square_all ys = match ys with | [] -> [] | hd::tl -> (square hd)::(map square tl) ;;

Page 38: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

POLY-HO!

Page 39: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Here’sanannoyingthing

39

WhatifIwanttoincrementalistoffloats?Alas,Ican’tjustcallthismap.Itworksonints!

let rec map (f:int->int) (xs:int list) : int list = match xs with | [] -> [] | hd::tl -> (f hd)::(map f tl);;

Page 40: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Here’sanannoyingthing

40

WhatifIwanttoincrementalistoffloats?Alas,Ican’tjustcallthismap.Itworksonints!

let rec map (f:int->int) (xs:int list) : int list = match xs with | [] -> [] | hd::tl -> (f hd)::(map f tl);;

let rec mapfloat (f:float->float) (xs:float list) : float list = match xs with | [] -> [] | hd::tl -> (f hd)::(mapfloat f tl);;

Page 41: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Turnsout

41

let rec map f xs = match xs with | [] -> [] | hd::tl -> (f hd)::(map f tl);; map (fun x -> x + 1) [1; 2; 3; 4] ;; map (fun x -> x +. 2.0) [3.1415; 2.718; 42.0] ;; map String.uppercase [“greg”; “victor”; “joe”] ;;

Page 42: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Typeoftheundecoratedmap?

42

let rec map f xs = match xs with | [] -> [] | hd::tl -> (f hd)::(map f tl) ;; map : ('a -> 'b) -> 'a list -> 'b list

Page 43: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Typeoftheundecoratedmap?

43

Readas:foranytypes'aand'b,ifyougivemapafuncJonfrom'ato'b,itwillreturnafuncJonwhichwhengivenalistof'avalues,returnsalistof'bvalues.

let rec map f xs = match xs with | [] -> [] | hd::tl -> (f hd)::(map f tl) ;; map : ('a -> 'b) -> 'a list -> 'b list

WeogenusegreekleOerslikeαorβtorepresenttype

variables.

Page 44: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Wecansaythisexplicitly

44

TheOCamlcompilerissmartenoughtofigureoutthatthisisthe

mostgeneraltypethatyoucanassigntothecode.Wesaymapispolymorphicinthetypes'aand'b–justafancy

waytosaymapcanbeusedonanytypes'aand'b.JavagenericsderivedfromML-stylepolymorphism(butadded

agerthefactandmorecomplicatedduetosubtyping)

let rec map (f:'a -> 'b) (xs:'a list) : 'b list = match xs with | [] -> [] | hd::tl -> (f hd)::(map f tl) ;; map : (‘a -> ‘b) -> ‘a list -> ‘b list

Page 45: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

MorerealisJcpolymorphicfuncJons

45

let rec merge (lt:'a->'a->bool) (xs:'a list) (ys:'a list) : 'a list =

match (xs,ys) with | ([],_) -> ys

| (_,[]) -> xs

| (x::xst, y::yst) ->

if lt x y then x::(merge lt xst ys) else y::(merge lt xs yst) ;;

let rec split (xs:'a list) (ys:'a list) (zs:'a list) : 'a list * 'a list =

match xs with | [] -> (ys, zs) | x::rest -> split rest zs (x::ys) ;;

let rec mergesort (lt:'a->'a->bool) (xs:'a list) : 'a list = match xs with | ([] | _::[]) -> xs

| _ -> let (first,second) = split xs [] [] in merge lt (mergesort lt first) (mergesort lt second) ;;

Page 46: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

MorerealisJcpolymorphicfuncJons

46

mergesort : ('a->'a->bool) -> 'a list -> 'a list

mergesort (<) [3;2;7;1]

== [1;2;3;7]

mergesort (>) [2.718; 3.1415; 42.0]

== [42.0 ; 3.1415; 2.718]

mergesort (fun x y -> String.compare x y < 0) [“Hi”; “Bi”] == [“Bi”; “Hi”]

let int_sort = mergesort (<) ;; let int_sort_down = mergesort (>) ;; let str_sort = mergesort (fun x y -> String.compare x y < 0) ;;

Page 47: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

let mystery = fun x -> (add 1) (square x) ;;

AnotherInteresJngFuncJon

47

let comp f g x = f (g x) ;; let mystery = comp (add 1) square ;;

let comp = fun f -> (fun g -> (fun x -> f (g x))) ;; let mystery = comp (add 1) square ;;

let mystery = (fun f -> (fun g -> (fun x -> f (g x)))) (add 1) square ;;

let mystery x = add 1 (square x) ;;

Page 48: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

OpJmizaJon

48

map f (map g [x1; x2; …; xn])

Whatdoesthisprogramdo?

Foreachelementofthelistx1,x2,x3...xn,itexecutesg,creaJng:

map f ([g x1; g x2; …; g xn])

Thenforeachelementofthelist[gx1,gx2,gx3...gxn],itexecutesf,creaJng:

[f (g x1); f (g x2); …; f (g xn)]

Isthereafasterway? Yes!(AndqueryopJmizersforSQLdoitforyou.)

map (comp f g) [x1; x2; ...; xn]

Page 49: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

DeforestaJon

49

map f (map g [x1; x2; …; xn])

map (comp f g) [x1; x2; ...; xn]

ThiskindofopJmizaJonhasaname:

deforestaJon(becauseiteliminatesintermediatelistsand,um,trees…)

Page 50: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Whatisthetypeofcomp?

50

let comp f g x = f (g x) ;;

Page 51: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Whatisthetypeofcomp?

51

comp : ('b -> 'c) -> ('a -> 'b) -> ('a -> 'c)

let comp f g x = f (g x) ;;

Page 52: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Howaboutreduce?

52

let rec reduce f u xs = match xs with

| [] -> u | hd::tl -> f hd (reduce f u tl);;

What’sthemostgeneraltypeofreduce?

Page 53: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Howaboutreduce?

53

let rec reduce f u xs = match xs with

| [] -> u | hd::tl -> f hd (reduce f u tl);;

What’sthemostgeneraltypeofreduce?

BasedonthepaOerns,we

knowxsmustbea('alist)forsometype'a.

Page 54: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Howaboutreduce?

54

let rec reduce f u (xs: 'a list) = match xs with

| [] -> u | hd::tl -> f hd (reduce f u tl);;

What’sthemostgeneraltypeofreduce?

Page 55: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Howaboutreduce?

55

let rec reduce f u (xs: 'a list) = match xs with

| [] -> u | hd::tl -> f hd (reduce f u tl);;

What’sthemostgeneraltypeofreduce?

fiscalledsoitmustbea

funcJonoftwoarguments.

Page 56: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Howaboutreduce?

56

let rec reduce (f:? -> ? -> ?) u (xs: 'a list) = match xs with

| [] -> u | hd::tl -> f hd (reduce f u tl);;

What’sthemostgeneraltypeofreduce?

Page 57: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Howaboutreduce?

57

let rec reduce (f:? -> ? -> ?) u (xs: 'a list) = match xs with

| [] -> u | hd::tl -> f hd (reduce f u tl);;

What’sthemostgeneraltypeofreduce?

Furthermore,hdcamefromxs,sofmusttakean'avalueasitsfirst

argument.

Page 58: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Howaboutreduce?

58

let rec reduce (f:'a -> ? -> ?) u (xs: 'a list) = match xs with

| [] -> u | hd::tl -> f hd (reduce f u tl);;

What’sthemostgeneraltypeofreduce?

Page 59: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Howaboutreduce?

59

let rec reduce (f:'a -> ? -> ?) u (xs: 'a list) = match xs with

| [] -> u | hd::tl -> f hd (reduce f u tl);;

What’sthemostgeneraltypeofreduce?

Thesecondargumenttofmusthavethe

sametypeastheresultofreduce.Let’scallit'b.

Page 60: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Howaboutreduce?

60

let rec reduce (f:'a -> 'b -> ?) u (xs: 'a list) : 'b = match xs with

| [] -> u | hd::tl -> f hd (reduce f u tl);;

What’sthemostgeneraltypeofreduce?

Theresultoffmusthavethe

sametypeastheresultofreduce

overall:'b.

Page 61: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Howaboutreduce?

61

let rec reduce (f:'a -> 'b -> 'b) u (xs: 'a list) : 'b = match xs with

| [] -> u | hd::tl -> f hd (reduce f u tl);;

What’sthemostgeneraltypeofreduce?

Page 62: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Howaboutreduce?

62

let rec reduce (f:'a -> 'b -> ?) u (xs: 'a list) : 'b = match xs with

| [] -> u | hd::tl -> f hd (reduce f u tl);;

What’sthemostgeneraltypeofreduce?

Ifxsisempty,thenreduce

returnsu.Sou’stypemustbe'b.

Page 63: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Howaboutreduce?

63

let rec reduce (f:'a -> 'b -> 'b) (u:'b) (xs: 'a list) : 'b = match xs with

| [] -> u | hd::tl -> f hd (reduce f u tl);;

What’sthemostgeneraltypeofreduce?

Page 64: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Howaboutreduce?

64

let rec reduce (f:'a -> 'b -> 'b) (u:'b) (xs: 'a list) : 'b = match xs with

| [] -> u | hd::tl -> f hd (reduce f u tl);;

What’sthemostgeneraltypeofreduce?

('a -> 'b -> 'b) -> 'b -> 'a list -> 'b

Page 65: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

TheListLibrary

65

NB:mapandreducearealreadydefinedintheListlibrary.–  However,reduceiscalled“fold_right”.–  (Goodbetthere’sa“fold_leg”too.)

I’llusereduceinsteadoffold_right,for3reasons:–  AnalogywithGoogle’sMap/Reduce–  Thelibrary’sargumentstofold_rightareinthe"wrong"order–  Makestheexamplefitonaslide.

Page 66: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

Summary

66

•  Mapandreducearetwohigher-orderfunc6onsthatcapturevery,verycommonrecursionpaFerns

•  Reduceisespeciallypowerful:–  relatedtothe“visitorpaOern”ofOOlanguageslikeJava.–  canimplementmostlist-processingfuncJonsusingit,includingthingslikecopy,append,filter,reverse,map,etc.

•  Wecanwriteclear,terse,reusablecodebyexploiJng:–  higher-orderfuncJons–  anonymousfuncJons–  first-classfuncJons–  polymorphism

Page 67: Poly-HO!Poly-HO! polymorphic, higher-order programming COS 326 David Walker Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel permission granted to reuse

PracJceProblems

67

Usingmap,writeafuncJonthattakesalistofpairsofintegers,andproducesalistofthesumsofthepairs.

–  e.g.,list_add[(1,3);(4,2);(3,0)]=[4;6;3]–  Writelist_adddirectlyusingreduce.

Usingmap,writeafuncJonthattakesalistofpairsofintegers,andproducestheirquoJentifitexists.

–  e.g.,list_div[(1,3);(4,2);(3,0)]=[Some0;Some2;None]–  Writelist_divdirectlyusingreduce.

Usingreduce,writeafuncJonthattakesalistofopJonalintegers,andfiltersoutalloftheNone’s.

–  e.g.,filter_none[Some0;Some2;None;Some1]=[0;2;1]–  Whycan’twedirectlyusefilter?Howwouldyougeneralizefiltersothat

youcancomputefilter_none?AlternaJvely,rigupasoluJonusingfilter+map.

Usingreduce,writeafuncJontocomputethesumofsquaresofalistofnumbers.

–  e.g.,sum_squares=[3,5,2]=38