All You Need is Fold

Post on 26-Jan-2017

385 views 0 download

Transcript of All You Need is Fold

All You Need is Fold Mike Harris

All You Need Is FOLD

All You Need Is FOLD

All you need is FOLD

FOLD

Fold is All You Need!

Tour

• Backstage

• Concert

• Farewell

Backstage

f

g

Function

f g

f(g)

Function

Fold

a1

a2

an

b

Fold

foldr :: (α → β → β) → β → ([α] → β)foldl :: (β → α→ β) → β → ([α] → β)

SeedFunc

a1

a2

an

Fold b

Given

We

Func

Seed

f anf a2f Seed a1

f anf a2f(Seed, a1)

f anf(f(Seed, a1), a2)

b

Fold

a1

a2

an

b

— Paul FeyerabendAgainst Method Chapter 16

“Fundamental conceptual change … presupposes new world-views and

new languages capable of expressing them.”

Concert

All You Need is Fold

Set List

• And

• Or

• Length

• Reverse

• Map

• Filter

• Zip

Set List

• And

• Or

• Length

• Reverse

• Map

• Filter

• Zip

And

T/F

T/F

T/F

T/F

And

and :: [Bool] → Booland = fold (∧) True

TrueAnd

f1

f2

fn

Fold f

Given

We

And

True

And

True And

foldAnd = (...facts) => { _.foldl(

facts, (m, x) => m && x, true);

};And True

foldAnd(false, true, false);

And

True

False True False

And

And

True

False True False

M

X

result False

And

And

False

True False

M

X

result False

And

And

False

False

M

X

result False

And

And

True

False True False

result False

And

foldAnd = (...facts) => { _.foldl(

facts, (m, x) => m && x, true);

};And True

Set List

• And

• Or

• Length

• Reverse

• Map

• Filter

• Zip

Or

T/F

T/F

T/F

T/F

Or

or :: [Bool] → Boolor = fold (∨) False

FalseOr

f1

f2

fn

Fold f

Given

We

Or

False

Or

False Or

foldOr = (...facts) => { _.foldl(

facts, (m, x) => m || x, false);

};Or False

foldOr(false, true, false);

Or

False

False True False

Or

Or

False

False True False

M

X

result False

Or

Or

False

True False

M

X

result True

Or

Or

True

False

M

X

result True

Or

Or

False

False True False

result True

Or

foldOr = (...facts) => { _.foldl(

facts, (m, x) => m || x, false);

};Or False

Set List

• And

• Or

• Length

• Reverse

• Map

• Filter

• Zip

Length size

Length

length :: [α] → Intlength = fold (λx n → 1 + n) 0

0+ 1

x1

x2

xn

Fold #

Given

We

+ 1

0

+ 1

0 Length

foldLength = (coll) => { _.foldl(

coll, m => m + 1, 0);

};+ 1 0

foldLength([…'Mike']);

+ 1

0

M i k e

Length

+ 1

0M

result 1

M i k e

Length

+ 1

1M

result 2

i k e

Length

+ 1

2M

result 3

k e

Length

+ 1

3M

result 4

e

Length

+ 1

0

result 4

M i k e

Length

foldLength = (coll) => { _.foldl(

coll, m => m + 1, 0);

};+ 1 0

Set List

• And

• Or

• Length

• Reverse

• Map

• Filter

• Zip

Reverse

x1

x2

xn

xn

x2

x1

Reverse

reverse :: [α] → [α]reverse = fold (λx m → m ++ [x]) [ ]

[ ]Cons

x1

x2

xn

Fold [x]

Given

We

Cons

[ ]

Cons

[ ] Reverse

foldReverse = (coll) => { _.foldl(

coll, (m, x) => { m.unshift(x); return m; },

[]); }; Cons [ ]

foldReverse([…'Mike']);

Cons

[ ]

M i k e

Reverse

Cons

[ ]

M i k

M

X

result M

e

Reverse

Cons

M

i k e

M

X

result iM

Reverse

Cons

iM

k e

M

X

result kiM

Reverse

Cons

kiM

e

M

X

result ekiM

Reverse

Cons

[ ]

result ekiM

M i k e

Reverse

foldReverse = (coll) => { _.foldl(

coll, (m, x) => { m.unshift(x); return m; },

[]); }; Cons [ ]

Set List

• And

• Or

• Length

• Reverse

• Map

• Filter

• Zip

Map

x1

x2

xn

z1

z2

zn

func

Map

map :: (α → β) → ([α] → [β])map f = fold (λx xs → f x : xs) [ ]

[ ]Conj

x1

x2

xn

Fold [z]

Given

We

Conj

[ ]

Conj

[ ]

func

Map

foldMap = (f, coll) => { _.foldl(

coll, (m, x) => { m.push(f(x)); return m; },

[]); }; Conj [ ]

foldMap( s => s.toUpperCase(), […'Mike']);

Conj

[ ]

M i k e

upper

Map

Conj

[ ]

M i k

M

X

result M

e

upper

Map

Conj

M

i k e

M

X

result MIupper

Map

Conj

MI

k e

M

X

result MIKupper

Map

Conj

MIK

e

M

X

result MIKEupper

Map

Conj

[ ]

M i k

result

e

upper MIKE

Map

foldMap = (f, coll) => { _.foldl(

coll, (m, x) => { m.push(f(x)); return m; },

[]); }; Conj [ ]

Set List

• And

• Or

• Length

• Reverse

• Map

• Filter

• Zip

Filter

x1

x2

xn

x1

xn

pred

Filter

filter :: (α → Bool) → ([α] → [α])filter p = fold (λx xs → if p x then x : xs else xs) [ ]

if

Conj

[ ]

x1

x2

xn

Fold [x]

Given

We

[ ]

if

Conj

if

[ ]

pred Conj

Filter

foldFilter = (pred, coll) => { _.foldl(

coll, (m, x) => { if (pred(x)) m.push(x); return m; },

[]); }; [ ]if Conj

foldFilter( s => /^[a-z]*$/.test(s), […'Mike']);

if

[ ]

M i k e

isLower Conj

Filter

if

[ ]

M i k

M

X

result [ ]

e

isLower Conj

Filter

if

[ ]

i k e

M

X

isLower result iConj

Filter

if

i

k e

M

X

isLower result ikConj

Filter

if

ik

e

M

X

isLower result ikeConj

Filter

if

[ ]

isLower

M i k e

result ikeConj

Filter

foldFilter = (pred, coll) => { _.foldl(

coll, (m, x) => { if (pred(x)) m.push(x); return m; },

[]); }; [ ]if Conj

Set List

• And

• Or

• Length

• Reverse

• Map

• Filter

• Zip

Zip

y1

y2

yj

z1

z2

zk

funcx1

x2

xi

Zip

zip2 :: (α → β → γ) → ([α] → [β] → [γ])zip2 f = fold (λx y xs ys → f x y : xs ys) [ ]

[ ]Conj

y1

y2

ym

Fold [z]

Given

We

Conj

[ ]

x1

x2

xn

Conj

[ ]

func

Zip

foldZip = (f, xs, ys) => { _.foldl(

_.zip(xs, ys), (m, [x, y]) => { m.push(f(x, y)); return m; },

[]); }; Conj [ ]

foldZip( _.add, [1, 2], [10, 20]);

Conj

[ ]

1 2

+

10 20

Zip

Conj

[ ]

1 2

+

10 20

M

result 11

X

Y

Zip

Conj

11

2

+

20

M

result 11 22

X

Y

Zip

Conj

[ ]

+ result 11 22

1 2

10 20

Zip

foldZip = (f, xs, ys) => { _.foldl(

_.zip(xs, ys), (m, [x, y]) => { m.push(f(x, y)); return m; },

[]); }; Conj [ ]

Encore

Coin Changer

Change

coin1

coin2

coinn

c1

c2

cn

amount

Coin Changer kata

changeFor :: [α] → α → [α]changeFor a = fold (λa x xs → (a % x, a / x) : xs (a, [ ])

Conj

Changer

[ ]

amount

c1

c2

cn

Fold

Given

We

[c]

0

Conj

Changer

[ ]

amount

Conj

amount [ ]

Changer

Change

foldChange = (coins, amount) => { _.foldl(coins,

(m, coin) => { m.result.push( _.floor(m.result / coin)); m.amount %= coin; return m;

},{amount: amount, result: []}).result;

};Conj [ ]

Changer amount

foldChange( [25, 10, 5, 1], 99);

Conj

amount

25 10 5 1

[ ]

Changer

Change

Conj

99

25 10 5 1

[ ]M

X

result 24 3Changer

Change

Conj

24

10 5 1

3M

X

result 4 3 2Changer

Change

Conj

4

5 1

3 2M

X

result 4 3 2 0Changer

Change

Conj

4

1

3 2 0M

X

result 0 3 2 0 4Changer

Change

Conj result 0 3 2 0 4Changer

amount [ ]

25 10 5 1

Change

foldChange = (coins, amount) => { _.foldl(coins,

(m, coin) => { m.result.push( _.floor(m.result / coin)); m.amount %= coin; return m;

},{amount: amount, result: []}).result;

};Conj [ ]

Changer amount

— Paul FeyerabendAgainst Method Chapter 18

“[A]ll methodologies, even the most obvious ones, have their limits”

Thank you!

Mike Harris@MikeMKHhttp://comp-phil.blogspot.com/Remember, all you need is Fold!

Talks

• Rich Hickey - “Reducers”, EuroClojure 2012. https://vimeo.com/45561411

• Rich Hickey - “Transducers”, StrangeLoop 2014. https://www.youtube.com/watch?v=6mTbuzafcII

• Tomas Petricek - “History and Philosophy of Types”, StrangeLoop 2015. http://tpetricek.github.io/Talks/2015/philosophy-of-types/#/

Books

• Richard Bird and Phil Wadler - Introduction to Functional Programming. Prentice-Hall,1988.http://usi-pl.github.io/lc/sp-2015/doc/Bird_Wadler.%20Introduction%20to%20Functional%20Programming.1ed.pdf

• Paul Feyerabend - Against Method. Verso, 2010.

• Michael Fogus - Functional JavaScript: Introducing Functional Programming with Underscore.js. O’Reilly, 2013.http://functionaljavascript.com/

Papers

• Erik Meijer, Maarten Fokkinga, and Ross Paterson - “Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire”. http://eprints.eemcs.utwente.nl/7281/01/db-utwente-40501F46.pdf

• Graham Hutton - “A tutorial on the universality and expressiveness of fold”.http://www.cs.nott.ac.uk/~gmh/fold.pdf

Blog Posts

• Brian McNamara - “Catamorphisms, part one”https://lorgonblog.wordpress.com/2008/04/05/catamorphisms-part-one/

• Edward Kmett - “Catamorphisms”https://www.fpcomplete.com/user/edwardk/recursion-schemes/catamorphisms

Websites

• ClojureDocs - https://clojuredocs.org/

• HaskellWiki - https://wiki.haskell.org/Haskell

• Inside F# - https://lorgonblog.wordpress.com/

• lodash - https://lodash.com/docs

• MDN - https://developer.mozilla.org/en-US/

• ReactiveX - http://reactivex.io/

Images (in order used)• "Abbey Rd Studios" by Misterweiss at en.wikipedia - Transfered from en.wikipedia Transfer was stated to be made by User:Blast..

Licensed under Public Domain via Commons - https://commons.wikimedia.org/wiki/File:Abbey_Rd_Studios.jpg#/media/File:Abbey_Rd_Studios.jpg

• "60s wallpaper" by Domincspics - Flickr. Licensed under CC BY 2.0 via Commons - https://commons.wikimedia.org/wiki/File:60s_wallpaper.jpg#/media/File:60s_wallpaper.jpg

• "70's Wallpaper" by Liz Sullivan - Own work. Licensed under CC BY-SA 4.0 via Wikimedia Commons - https://commons.wikimedia.org/wiki/File:70%27s_Wallpaper.JPG#/media/File:70%27s_Wallpaper.JPG

• "Flickr - ronsaunders47 - The Beatles-Sgt Pepper backdrop.". Licensed under CC BY-SA 2.0 via Wikimedia Commons - https://commons.wikimedia.org/wiki/File:Flickr_-_ronsaunders47_-_The_Beatles-Sgt_Pepper_backdrop..jpg#/media/File:Flickr_-_ronsaunders47_-_The_Beatles-Sgt_Pepper_backdrop..jpg

• "All you need is love graffiti Osijek" by Objavljeno - Own work. Licensed under CC BY-SA 3.0 via Wikimedia Commons - https://commons.wikimedia.org/wiki/File:All_you_need_is_love_graffiti_Osijek.JPG#/media/File:All_you_need_is_love_graffiti_Osijek.JPG

• "Illumined Pleasure Salvador Dali" by Salvador Dalí - Own workMrArifnajafov (Photography from the original). Licensed under CC BY-SA 3.0 via Wikimedia Commons - https://commons.wikimedia.org/wiki/File:Illumined_Pleasure_Salvador_Dali.JPG#/media/File:Illumined_Pleasure_Salvador_Dali.JPG

• "3 Savile Row" by Original uploader was Misterweiss at en.wikipedia - Transfered from en.wikipedia Transfer was stated to be made by User:Vinhtantran.. Licensed under Public Domain via Commons - https://commons.wikimedia.org/wiki/File:3_Savile_Row.jpg#/media/File:3_Savile_Row.jpg

• "Paul Feyerabend 2" by Grazia Borrini-Feyerabend. Licensed under Attribution via Commons - https://commons.wikimedia.org/wiki/File:Paul_Feyerabend_2.jpg#/media/File:Paul_Feyerabend_2.jpg

Images (in order used)• "The Beatles on Green Hill in Almaty, Kazakhstan" by Ken and Nyetta - Flickr: The Beatles on

Green Hill in Almaty. Licensed under CC BY 2.0 via Commons - https://commons.wikimedia.org/wiki/File:The_Beatles_on_Green_Hill_in_Almaty,_Kazakhstan.jpg#/media/File:The_Beatles_on_Green_Hill_in_Almaty,_Kazakhstan.jpg

• "The Beatles in America" by United Press International, photographer unknown - This image is available from the United States Library of Congress's Prints and Photographs division under the digital ID cph.3c11094.This tag does not indicate the copyright status of the attached work.

• "The Beatles rooftop concert" by Source. Licensed under Fair use via Wikipedia - https://en.wikipedia.org/wiki/File:The_Beatles_rooftop_concert.jpg#/media/File:The_Beatles_rooftop_concert.jpg

• "Paul Feyerabend 2" by Grazia Borrini-Feyerabend. Licensed under Attribution via Commons - https://commons.wikimedia.org/wiki/File:Paul_Feyerabend_2.jpg#/media/File:Paul_Feyerabend_2.jpg

• Myself taken at StrangeLoop 2014 by my wife, Kelsey Harris