SlideShare a Scribd company logo
1 of 129
A Million Ways to
Fold in JS
Agenda
[Recursion, Corecursion, Transducers, Monoids, F-Algebras]
for (i = 0; i < xs.length; i++) {
xs[i] += 1;
}
Recursion
var sum = function(xs) {
if(xs.length === 0) return 0;
return first(xs) + sum(rest(xs));
}
var sum = function(xs) {
if(xs.length === 0) return 0;
return first(xs) + sum(rest(xs));
}
Base Case
Action
Recursion
var reverse = function(xs) {
if(xs.length === 0) return [];
return reverse(rest(xs)).concat(first(xs));
}
var reverse = function(xs) {
if(xs.length === 0) return [];
return reverse(rest(xs)).concat(first(xs));
}
Base Case
Action
Recursion
var sum = function(xs) {
if(xs.length === 0) return 0;
return first(xs) + sum(rest(xs));
}
sum([1,2,3])
// 1 + sum([2,3])
// 1 + (2 + sum([3]))
// 1 + (2 + (3 + sum([])))
// 1 + (2 + (3 + 0))
// 1 + (2 + 3)
// 1 + 5
//=> 6
ES6
ES6
ES6!
Err, i mean 2015
Tail Recursive
var sum = function(xs) {
if(xs.length === 0) return 0;
return first(xs) + sum(rest(xs));
}
var sum = function(xs) {
if(xs.length === 0) return 0;
return first(xs) + sum(rest(xs));
}
var sum = function(xs) {
if(xs.length === 0) return 0;
return first(xs) + sum(rest(xs));
}
RangeError: Maximum call stack size exceeded
var sum = function(xs) {
if(xs.length === 0) return 0;
return first(xs) + sum(rest(xs));
}
var sum = function(list) {
function go(acc, xs) {
if(xs.length === 0) return acc;
return go(acc+first(xs), rest(xs));
}
return go(0, list)
}
var sum = function(xs) {
if(xs.length === 0) return 0;
return first(xs) + sum(rest(xs));
}
var sum = function(list) {
function go(acc, xs) {
if(xs.length === 0) return acc;
return go(acc+first(xs), rest(xs));
}
return go(0, list)
}
var reduce = function(f, acc, xs) {
if(xs.length === 0) return acc;
return reduce(f, f(acc, first(xs)), rest(xs));
}
var reduce = function(f, acc, xs) {
if(xs.length === 0) return acc;
return reduce(f, f(acc, first(xs)), rest(xs));
}
var sum = function(xs){
return reduce((acc, x) => x + acc, 0, xs)
}
var reverse = function(xs) {
return reduce((acc, x) => [x].concat(acc), [], xs)
}
var map = function(f, xs) {
return reduce((acc, x) => acc.concat(f(x)), [], xs)
}
var filter = function(f, xs) {
return reduce((acc, x) => f(x) ? acc.concat(x) : acc, [], xs)
}
Catamorphism
+
any
all
size
max
min
sortBy
find
groupBy
first
last
take
drop
etc…
Any loop can be captured with a fold!
Apomorphism
Paramorphism
var para = function(f, acc, xs) {
if(xs.length === 0) return acc;
return para(f, f(acc, first(xs), xs), rest(xs));
}
var para = function(f, acc, xs) {
if(xs.length === 0) return acc;
return para(f, f(acc, first(xs), xs), rest(xs));
}
HORS
HORS
Agenda
[Corecursion, Transducers, Monoids, F-Algebras]
Recursion
Anamorphism
var unfold = function(f, seed) {
function go(f, seed, acc) {
var res = f(seed);
return res ? go(f, res[1], acc.concat([res[0]])) : acc;
}
return go(f, seed, [])
}
unfold(x => if(x < 26) [String.fromCharCode(x+65), x+1], 0);
//=> [A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z]
var range = function(i, count) {
return unfold(x => if(x <= count) [x, x+1], i);
}
range(5,10)
//=> [ 5, 6, 7, 8, 9, 10 ]
var tree = Node(Node(Leaf(2), 1, Leaf(3)), 0, Leaf(4))
fold((acc, x) => acc + x, 0, tree)
//=> 10
var clicks = $("#red-button").asEventStream("click")
fold((acc, el) => acc.append(el.id), $("#clicklog"), clicks)
//=> <div id=“clicklog”/>
var us = {
“391": "keith@suburban",
“52": “kaseem@funny.net"
}
fold((acc, addr) => acc.cc(addr), Email.create(), us)
//=> Email
Cons(3, Cons(4, Cons(5, Nil)));
tail3 tail4 tail5 Nil
Linked List
var Nil = {}
var _Cons = function(h, tl) {
this.head = h;
this.tail = tl;
};
var Cons = function(h, tl) { return new _Cons(h, tl) }
var lst = Cons(3, Cons(4, Cons(5, Nil)));
1
Node(Node(Leaf(2), 1, Leaf(3)), 0, Leaf(4))
2 3
64
5
7
Tree
var Empty = {}
var _Leaf = function(x) { this.x = x; }
var Leaf = function(x) { return new _Leaf(x) }
var _Node = function(l, x, r) {
this.left = l;
this.x = x;
this.right = r;
}
var Node = function(l, x, r) { return new _Node(l, x, r) }
Agenda
[Transducers, Monoids, F-Algebras]
Recursion
Corecursion
var map = function(f, xs) {
return reduce((acc, x) => concat(acc, f(x)), [], xs)
}
var map = function(f, xs) {
return reduce((acc, x) => concat(acc, f(x)), [], xs)
}
Accumulation
Transformation Iteration
var map = function(f, xs) {
return reduce((acc, x) => concat(acc, f(x)), [], xs)
}
var mapper = function(f) {
return (acc, x) => concat(acc, f(x))
}
reduce(mapper(x => x + 1), [], [1,2,3])
//=> [2,3,4]
var mapper = function(f) {
return (acc, x) => concat(acc, f(x))
}
reduce(mapper(x => x + 1), [], [1,2,3])
//=> [2,3,4]
var mapper = function(f, cnct) {
return (acc, x) => cnct(acc, f(x))
}
reduce(mapper(x => x + 1, concat), [], [1,2,3])
//=> [2,3,4]
var mapper = function(f, cnct) {
return (acc, x) => cnct(acc, f(x))
}
reduce(mapper(x => x + 1, concat), [], [1,2,3])
//=> [2,3,4]
var filterer = function(f, cnct) {
return (acc, x) => f(x) ? cnct(acc, x) : acc
}
reduce(filterer(x => x > 1, concat), [], [1,2,3])
//=> [2,3]
var filterer = function(f, cnct) {
return (acc, x) => f(x) ? cnct(acc, x) : acc
}
reduce(filterer(x => x > 1, concat), [], [1,2,3])
//=> [2,3]
var filterer = function(f, cnct) {
return (acc, x) => f(x) ? cnct(acc, x) : acc
}
reduce(filterer(x => x > 1, concat), [], [1,2,3])
//=> [2,3]
var copy = function(xs) {
return reduce(concat, [], xs)
}
filterer(x => x > 1, mapper(x => x + 1, concat))
//=> (acc, x) => x > 1 ? concat(acc, f(x)) : acc
filterer(x => x > 1, mapper(x => x + 1, concat))
//=> (acc, x) => x > 1 ? concat(acc, f(x)) : acc
reduce(filterer(x => x > 1,
mapper(x => x + 1, concat)),
[], [1,2,3])
//=> [3,4]
reduce(filterer(x => x > 1,
mapper(x => x + 1, concat)),
[], [1,2,3])
//=> [3,4]
reduce(filterer(x => x > 1,
mapper(x => x + 1, concat)),
[], [1,2,3])
//=> [3,4]
reduce(filterer(x => x > 1,
mapper(x => x + 1, append)),
Nil, Cons(1, Cons(2, Cons(3, Nil))))
//=> [3,4]
reduce(filterer(x => x > 1,
mapper(x => x + 1, append)),
Nil, Cons(1, Cons(2, Cons(3, Nil))))
//=> [3,4]
reduce(filterer(x => x > 1,
mapper(x => x + 1, insert)),
Empty, Node(Node(Leaf(2), 1, Leaf(3)), 0, Leaf(4)))
//=> [3,4]
reduce(filterer(x => x > 1,
mapper(x => x + 1, insert)),
Empty, Node(Node(Leaf(2), 1, Leaf(3)), 0, Leaf(4)))
//=> [3,4]
Iteration
Transformation
Accumulation
Agenda
[Monoids, F-Algebras]
Recursion
Corecursion
Transducers
// left identity
concat([], xs) == xs
// right identity
concat(xs, []) == xs
// associativity
concat(concat(xs, ys), zs) == concat(xs, concat(ys, zs))
var sum = function(xs) {
return reduce((acc, x) => acc + x, 0, xs)
}
var _Sum = function(x) { this.val = x }
var Sum = function(x){ return new _Sum(x) }
_Sum.prototype.concat = function(y){
return Sum(this.val + y.val)
}
_Sum.prototype.empty = function(){ return Sum(0) }
var sum = function(xs) {
return reduce((acc, x) => acc + x, 0, xs)
}
_Sum.prototype.concat = function(y){
return Sum(this.val + y.val)
}
_Sum.prototype.empty = function(){ return Sum(0) }
var sum = function(xs) {
return reduce((acc, x) => acc + x, 0, xs)
}
fold([Sum(1), Sum(2), Sum(3), Sum(4)])
//=> Sum(10)
_Sum.prototype.concat = function(y){
return Sum(this.val + y.val)
}
_Sum.prototype.empty = function(){ return Sum(0) }
fold([Product(1),Product(2),Product(3),Product(4)])
//=> Product(24)
_Product.prototype.concat = function(y){
return Product(this.val * y.val)
}
_Product.prototype.empty = function(){ return Product(1) }
fold([Max(11),Max(16),Max(3),Max(9)])
//=> Max(16)
_Max.prototype.concat = function(y){
return Max(this.val > y.val ? this.val : y.val)
}
_Max.prototype.empty = function(){ return Max(-Infinity) }
_All.prototype.concat = function(y){
return Any(this.val && y.val)
}
_All.prototype.empty = function(){ return All(true) }
fold([All(false), All(false), All(true), All(false)])
//=> All(false)
_Any.prototype.concat = function(y){
return Any(this.val || y.val)
}
_Any.prototype.empty = function(){ return Any(false) }
fold([Any(false), Any(false), Any(true), Any(false)])
//=> Any(true)
any
all
max
min
and
or
product
sum
find
contains
concat
toList
_Any.prototype.concat = function(y){
return Any(this.val || y.val)
}
_Any.prototype.empty = function(){ return Any(false) }
fold([Any(false), Any(false), Any(true), Any(false)])
//=> Any(true)
var foldMap = function(f,xs) {
return compose(fold, map(f))(xs);
}
var sum = function(xs){ return foldMap(Sum, xs).val }
var max = function(xs){ return foldMap(Max, xs).val }
var any = function(xs){ return foldMap(Any, xs).val }
var tree = Node(Node(Leaf(2), 1, Leaf(3)), 2, Leaf(4))
sum(tree)
//=> 12
product(tree)
//=> 38
max(tree)
//=> 4
var lst = Cons(true, Cons(false, Cons(true, Nil)))
any(lst)
//=> true
all(lst)
//=> false
Iteration
Transformation
Accumulation
[Sum(a)] -> Sum(a)
[Product(a)] -> Product(a)
[Max(a)] -> Max(a)
F(a) -> a
Agenda
[F-Algebras]
Recursion
Corecursion
Transducers
Monoids
No, not
That F
var cata = function(f, xs) {
return f(xs.map(ys => cata(f,ys)))
}
var cata = function(f, xs) {
return f(xs.map(ys => cata(f,ys)))
}
var cata = function(f, xs) {
return f(xs.map(ys => cata(f,ys)))
}
Fixed point of a Functor
Nil.map = function(f) { return Nil; }
_Cons.prototype.map = function(f) {
return Cons(this.head, f(this.tail))
}
var sum = function(x) {
return (x === Nil) ? 0 : x.head + x.tail
}
var lst = Cons(2, Cons(3, Cons(4, Nil)));
cata(sum, lst);
//=> 9
var sum = function(x) {
return (x === Nil) ? 0 : x.head + x.tail
}
var lst = Cons(2, Cons(3, Cons(4, Nil)));
cata(sum, lst);
//=> 9
Algebra
var sum = function(x) {
return (x === Nil) ? 0 : x.head + x.tail
}
var lst = Cons(2, Cons(3, Cons(4, Nil)));
cata(sum, lst);
// Nil
// Cons(4, 0)
// Cons(3, 4)
// Cons(2, 7)
//=> 9
map(x => x + 1, Cons(2, Cons(3, Cons(4, Nil))))
//=> Cons(3, Cons(4, Cons(5, Nil)))
var map = function(f, xs) {
return cata(x => (x == Nil) ? Nil : Cons(f(x.head), x.tail), xs)
}
Empty.map = function(f) { return Empty }
_Leaf.prototype.map = function(f) {
return Leaf(this.x)
}
_Node.prototype.map = function(f) {
return Node(f(this.left), this.x, f(this.right))
}
cata(t =>
switch (t.constructor) {
case _Node: return t.left + t.x + t.right;
case _Leaf: return t.x;
default: 0;
}, tr)
//=> 10
var tr = Node(Node(Leaf(2), 1, Leaf(3)), 0, Leaf(4))
var ana = function(g, a) {
return g(a).map(x => ana(g,x))
}
var ana = function(g, a) {
return g(a).map(x => ana(g,x))
}
var arrToList = function(xs) {
return xs.length === 0 ? Nil : Cons(first(xs), rest(xs))
}
ana(arrToList, [1,2,3,4,5])
//=> Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Nil)))))
CoAlgebra
var arrToList = function(xs) {
return xs.length === 0 ? Nil : Cons(first(xs), rest(xs))
}
ana(arrToList, [1,2,3,4,5])
//=> Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Nil)))))
Co-Scary
var arrToList = function(xs) {
return xs.length === 0 ? Nil : Cons(first(xs), rest(xs))
}
ana(arrToList, [1,2,3,4,5])
//=> Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Nil)))))
var makeAlphabet = function(x) {
if(x > 25) return Nil;
return Cons(String.fromCharCode(x+65), x+1);
}
ana(makeAlphabet, 0)
//=> Cons(A, Cons(B, Cons(C, Cons(D, Cons(E, Cons(F, Cons(G, Cons(H
var range = function(acc, count) {
return ana(x => (x >= count) ? Nil : Cons(x, x+1), acc)
}
range(2, 10)
//=> Cons(2, Cons(3, Cons(4, Cons(5, Cons(6, Cons(7, Cons(8,
Cons(9, Nil))))))))
Iteration
Transformation
Accumulation
Mul(Add(Const(2), Const(3)), Const(4))
Mul(Add(Const(2), Const(3)), Const(4))
var _Const = function(val) { this.val = val }
var Const = function(x) { return new _Const(x) }
var _Add = function(x, y) {
this.x = x;
this.y = y;
}
var Add = function(x, y) { return new _Add(x, y) }
var _Mul = function(x, y) {
this.x = x
this.y = y
}
var Mul = function(x, y) { return new _Mul(x, y) }
_Const.prototype.map = function(f) { return this }
_Add.prototype.map = function(f) {
return Add(f(this.x), f(this.y))
}
_Mul.prototype.map = function(f) {
return Mul(f(this.x), f(this.y))
}
var interpret = function(a) {
switch(a.constructor) {
case _Mul: return a.x * a.y;
case _Add: return a.x + a.y;
case _Const: return a.val;
}
}
var program = Mul(Add(Const(2), Const(3)), Const(4))
cata(interpret, program);
//=> 20
var _Concat = function(v, next) {
this.val = v;
this.next = next;
}
var Concat = function(v, x){ return new _Concat(v, x) }
var _Replace = function(v, x, next) {
this.val = v;
this.x = x;
this.next = next;
}
var Replace = function(v, x, nt){ return new _Replace(v, x, nt) }
var _Input = function(v) { this.val = v }
var Input = function(v){ return new _Input(v) }
_Concat.prototype.map = function(f) {
return Concat(this.val, f(this.next))
}
_Replace.prototype.map = function(f) {
return Replace(this.val, this.x, f(this.next))
}
_Input.prototype.map = function(f) {
return Input(this.val)
}
var interpret = function(t) {
switch (t.constructor) {
case _Concat: return t.next.concat(t.val);
case _Replace: return t.next.replace(t.val, t.x);
case _Input: return t.val;
}
}
var prog = Concat("world", Replace("h", "m", Input(“hello")))
cata(interpret, prog)
//=> melloworld
var interpret1 = function(t) {
switch (t.constructor) {
case _Concat:
return "concatting “+t.val+" after "+t.next;
case _Replace:
return "replacing "+t.val+" with "+t.x+" on "+t.next;
case _Input:
return t.val;
}
}
var prog = Concat("world", Replace("h", "m", Input(“hello")))
cata(interpret1, prog)
//=> concatting world after replacing h with m on hello
Agenda
Recursion
Corecursion
Transducers
Monoids
F-Alegbras
THanks!
@drboolean
https://github.com/DrBoolean/RecursionTalk

More Related Content

What's hot

하스켈 프로그래밍 입문 3
하스켈 프로그래밍 입문 3하스켈 프로그래밍 입문 3
하스켈 프로그래밍 입문 3Kwang Yul Seo
 
関数潮流(Function Tendency)
関数潮流(Function Tendency)関数潮流(Function Tendency)
関数潮流(Function Tendency)riue
 
Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014Baruch Sadogursky
 
하스켈 프로그래밍 입문 4
하스켈 프로그래밍 입문 4하스켈 프로그래밍 입문 4
하스켈 프로그래밍 입문 4Kwang Yul Seo
 
Implementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 reduxImplementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 reduxEleanor McHugh
 
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...PROIDEA
 
Hitchhiker's Guide to Functional Programming
Hitchhiker's Guide to Functional ProgrammingHitchhiker's Guide to Functional Programming
Hitchhiker's Guide to Functional ProgrammingSergey Shishkin
 
imager package in R and examples..
imager package in R and examples..imager package in R and examples..
imager package in R and examples..Dr. Volkan OBAN
 
Advanced Data Visualization Examples with R-Part II
Advanced Data Visualization Examples with R-Part IIAdvanced Data Visualization Examples with R-Part II
Advanced Data Visualization Examples with R-Part IIDr. Volkan OBAN
 
Stanfy MadCode Meetup #9: Functional Programming 101 with Swift
Stanfy MadCode Meetup #9: Functional Programming 101 with SwiftStanfy MadCode Meetup #9: Functional Programming 101 with Swift
Stanfy MadCode Meetup #9: Functional Programming 101 with SwiftStanfy
 
The Groovy Puzzlers – The Complete 01 and 02 Seasons
The Groovy Puzzlers – The Complete 01 and 02 SeasonsThe Groovy Puzzlers – The Complete 01 and 02 Seasons
The Groovy Puzzlers – The Complete 01 and 02 SeasonsBaruch Sadogursky
 
Transducers in JavaScript
Transducers in JavaScriptTransducers in JavaScript
Transducers in JavaScriptPavel Forkert
 

What's hot (18)

하스켈 프로그래밍 입문 3
하스켈 프로그래밍 입문 3하스켈 프로그래밍 입문 3
하스켈 프로그래밍 입문 3
 
関数潮流(Function Tendency)
関数潮流(Function Tendency)関数潮流(Function Tendency)
関数潮流(Function Tendency)
 
Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014
 
Scala Parallel Collections
Scala Parallel CollectionsScala Parallel Collections
Scala Parallel Collections
 
하스켈 프로그래밍 입문 4
하스켈 프로그래밍 입문 4하스켈 프로그래밍 입문 4
하스켈 프로그래밍 입문 4
 
Scala by Luc Duponcheel
Scala by Luc DuponcheelScala by Luc Duponcheel
Scala by Luc Duponcheel
 
Functional programming in scala
Functional programming in scalaFunctional programming in scala
Functional programming in scala
 
Implementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 reduxImplementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 redux
 
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
 
Hitchhiker's Guide to Functional Programming
Hitchhiker's Guide to Functional ProgrammingHitchhiker's Guide to Functional Programming
Hitchhiker's Guide to Functional Programming
 
imager package in R and examples..
imager package in R and examples..imager package in R and examples..
imager package in R and examples..
 
Kotlin class
Kotlin classKotlin class
Kotlin class
 
Advanced Data Visualization Examples with R-Part II
Advanced Data Visualization Examples with R-Part IIAdvanced Data Visualization Examples with R-Part II
Advanced Data Visualization Examples with R-Part II
 
Stanfy MadCode Meetup #9: Functional Programming 101 with Swift
Stanfy MadCode Meetup #9: Functional Programming 101 with SwiftStanfy MadCode Meetup #9: Functional Programming 101 with Swift
Stanfy MadCode Meetup #9: Functional Programming 101 with Swift
 
The Groovy Puzzlers – The Complete 01 and 02 Seasons
The Groovy Puzzlers – The Complete 01 and 02 SeasonsThe Groovy Puzzlers – The Complete 01 and 02 Seasons
The Groovy Puzzlers – The Complete 01 and 02 Seasons
 
2.3 implicits
2.3 implicits2.3 implicits
2.3 implicits
 
Transducers in JavaScript
Transducers in JavaScriptTransducers in JavaScript
Transducers in JavaScript
 
Scala collections
Scala collectionsScala collections
Scala collections
 

Viewers also liked

Viewers also liked (8)

Fact, Fiction, and FP
Fact, Fiction, and FPFact, Fiction, and FP
Fact, Fiction, and FP
 
Functional Reactive Programming in Javascript
Functional Reactive Programming in JavascriptFunctional Reactive Programming in Javascript
Functional Reactive Programming in Javascript
 
Ricky Bobby's World
Ricky Bobby's WorldRicky Bobby's World
Ricky Bobby's World
 
Lenses
LensesLenses
Lenses
 
Functional js class
Functional js classFunctional js class
Functional js class
 
Js for learning
Js for learningJs for learning
Js for learning
 
Liftin every day
Liftin every dayLiftin every day
Liftin every day
 
Underscore
UnderscoreUnderscore
Underscore
 

Similar to Millionways

Intro to Functional Programming Workshop (code4lib)
Intro to Functional Programming Workshop (code4lib)Intro to Functional Programming Workshop (code4lib)
Intro to Functional Programming Workshop (code4lib)Will Kurt
 
Jscex: Write Sexy JavaScript (中文)
Jscex: Write Sexy JavaScript (中文)Jscex: Write Sexy JavaScript (中文)
Jscex: Write Sexy JavaScript (中文)jeffz
 
TI1220 Lecture 6: First-class Functions
TI1220 Lecture 6: First-class FunctionsTI1220 Lecture 6: First-class Functions
TI1220 Lecture 6: First-class FunctionsEelco Visser
 
Futures e abstração - QCon São Paulo 2015
Futures e abstração - QCon São Paulo 2015Futures e abstração - QCon São Paulo 2015
Futures e abstração - QCon São Paulo 2015Leonardo Borges
 
深入浅出Jscex
深入浅出Jscex深入浅出Jscex
深入浅出Jscexjeffz
 
Monadologie
MonadologieMonadologie
Monadologieleague
 
Jscex: Write Sexy JavaScript
Jscex: Write Sexy JavaScriptJscex: Write Sexy JavaScript
Jscex: Write Sexy JavaScriptjeffz
 
Christian Gill ''Functional programming for the people''
Christian Gill ''Functional programming for the people''Christian Gill ''Functional programming for the people''
Christian Gill ''Functional programming for the people''OdessaJS Conf
 
Javascript Uncommon Programming
Javascript Uncommon ProgrammingJavascript Uncommon Programming
Javascript Uncommon Programmingjeffz
 
Introduction to Functional Programming with Haskell and JavaScript
Introduction to Functional Programming with Haskell and JavaScriptIntroduction to Functional Programming with Haskell and JavaScript
Introduction to Functional Programming with Haskell and JavaScriptWill Kurt
 
Fp in scala with adts part 2
Fp in scala with adts part 2Fp in scala with adts part 2
Fp in scala with adts part 2Hang Zhao
 
Java 8 - An Introduction by Jason Swartz
Java 8 - An Introduction by Jason SwartzJava 8 - An Introduction by Jason Swartz
Java 8 - An Introduction by Jason SwartzJason Swartz
 
Introduction to R programming
Introduction to R programmingIntroduction to R programming
Introduction to R programmingAlberto Labarga
 
Truth, deduction, computation lecture g
Truth, deduction, computation   lecture gTruth, deduction, computation   lecture g
Truth, deduction, computation lecture gVlad Patryshev
 
Fp in scala part 2
Fp in scala part 2Fp in scala part 2
Fp in scala part 2Hang Zhao
 

Similar to Millionways (20)

Intro to Functional Programming Workshop (code4lib)
Intro to Functional Programming Workshop (code4lib)Intro to Functional Programming Workshop (code4lib)
Intro to Functional Programming Workshop (code4lib)
 
Jscex: Write Sexy JavaScript (中文)
Jscex: Write Sexy JavaScript (中文)Jscex: Write Sexy JavaScript (中文)
Jscex: Write Sexy JavaScript (中文)
 
TI1220 Lecture 6: First-class Functions
TI1220 Lecture 6: First-class FunctionsTI1220 Lecture 6: First-class Functions
TI1220 Lecture 6: First-class Functions
 
Futures e abstração - QCon São Paulo 2015
Futures e abstração - QCon São Paulo 2015Futures e abstração - QCon São Paulo 2015
Futures e abstração - QCon São Paulo 2015
 
深入浅出Jscex
深入浅出Jscex深入浅出Jscex
深入浅出Jscex
 
Swift study: Closure
Swift study: ClosureSwift study: Closure
Swift study: Closure
 
Monadologie
MonadologieMonadologie
Monadologie
 
Jscex: Write Sexy JavaScript
Jscex: Write Sexy JavaScriptJscex: Write Sexy JavaScript
Jscex: Write Sexy JavaScript
 
Christian Gill ''Functional programming for the people''
Christian Gill ''Functional programming for the people''Christian Gill ''Functional programming for the people''
Christian Gill ''Functional programming for the people''
 
Javascript Uncommon Programming
Javascript Uncommon ProgrammingJavascript Uncommon Programming
Javascript Uncommon Programming
 
Introduction to Functional Programming with Haskell and JavaScript
Introduction to Functional Programming with Haskell and JavaScriptIntroduction to Functional Programming with Haskell and JavaScript
Introduction to Functional Programming with Haskell and JavaScript
 
Fp in scala with adts part 2
Fp in scala with adts part 2Fp in scala with adts part 2
Fp in scala with adts part 2
 
purrr.pdf
purrr.pdfpurrr.pdf
purrr.pdf
 
Java 8 - An Introduction by Jason Swartz
Java 8 - An Introduction by Jason SwartzJava 8 - An Introduction by Jason Swartz
Java 8 - An Introduction by Jason Swartz
 
Introduction to R programming
Introduction to R programmingIntroduction to R programming
Introduction to R programming
 
Lambda calculus
Lambda calculusLambda calculus
Lambda calculus
 
Truth, deduction, computation lecture g
Truth, deduction, computation   lecture gTruth, deduction, computation   lecture g
Truth, deduction, computation lecture g
 
Fp in scala part 2
Fp in scala part 2Fp in scala part 2
Fp in scala part 2
 
ES6(ES2015) is beautiful
ES6(ES2015) is beautifulES6(ES2015) is beautiful
ES6(ES2015) is beautiful
 
Clojure to Slang
Clojure to SlangClojure to Slang
Clojure to Slang
 

Recently uploaded

Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfRankYa
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 

Recently uploaded (20)

Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdf
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 

Millionways

  • 1. A Million Ways to Fold in JS
  • 2.
  • 4.
  • 5. for (i = 0; i < xs.length; i++) { xs[i] += 1; }
  • 6.
  • 8. var sum = function(xs) { if(xs.length === 0) return 0; return first(xs) + sum(rest(xs)); }
  • 9. var sum = function(xs) { if(xs.length === 0) return 0; return first(xs) + sum(rest(xs)); } Base Case Action Recursion
  • 10. var reverse = function(xs) { if(xs.length === 0) return []; return reverse(rest(xs)).concat(first(xs)); }
  • 11. var reverse = function(xs) { if(xs.length === 0) return []; return reverse(rest(xs)).concat(first(xs)); } Base Case Action Recursion
  • 12. var sum = function(xs) { if(xs.length === 0) return 0; return first(xs) + sum(rest(xs)); } sum([1,2,3]) // 1 + sum([2,3]) // 1 + (2 + sum([3])) // 1 + (2 + (3 + sum([]))) // 1 + (2 + (3 + 0)) // 1 + (2 + 3) // 1 + 5 //=> 6
  • 13.
  • 14. ES6
  • 15. ES6
  • 18. var sum = function(xs) { if(xs.length === 0) return 0; return first(xs) + sum(rest(xs)); }
  • 19. var sum = function(xs) { if(xs.length === 0) return 0; return first(xs) + sum(rest(xs)); }
  • 20. var sum = function(xs) { if(xs.length === 0) return 0; return first(xs) + sum(rest(xs)); } RangeError: Maximum call stack size exceeded
  • 21. var sum = function(xs) { if(xs.length === 0) return 0; return first(xs) + sum(rest(xs)); } var sum = function(list) { function go(acc, xs) { if(xs.length === 0) return acc; return go(acc+first(xs), rest(xs)); } return go(0, list) }
  • 22. var sum = function(xs) { if(xs.length === 0) return 0; return first(xs) + sum(rest(xs)); } var sum = function(list) { function go(acc, xs) { if(xs.length === 0) return acc; return go(acc+first(xs), rest(xs)); } return go(0, list) }
  • 23. var reduce = function(f, acc, xs) { if(xs.length === 0) return acc; return reduce(f, f(acc, first(xs)), rest(xs)); }
  • 24. var reduce = function(f, acc, xs) { if(xs.length === 0) return acc; return reduce(f, f(acc, first(xs)), rest(xs)); }
  • 25. var sum = function(xs){ return reduce((acc, x) => x + acc, 0, xs) } var reverse = function(xs) { return reduce((acc, x) => [x].concat(acc), [], xs) }
  • 26. var map = function(f, xs) { return reduce((acc, x) => acc.concat(f(x)), [], xs) } var filter = function(f, xs) { return reduce((acc, x) => f(x) ? acc.concat(x) : acc, [], xs) }
  • 28.
  • 30. Any loop can be captured with a fold!
  • 33. var para = function(f, acc, xs) { if(xs.length === 0) return acc; return para(f, f(acc, first(xs), xs), rest(xs)); }
  • 34. var para = function(f, acc, xs) { if(xs.length === 0) return acc; return para(f, f(acc, first(xs), xs), rest(xs)); }
  • 35. HORS
  • 36. HORS
  • 39. var unfold = function(f, seed) { function go(f, seed, acc) { var res = f(seed); return res ? go(f, res[1], acc.concat([res[0]])) : acc; } return go(f, seed, []) }
  • 40. unfold(x => if(x < 26) [String.fromCharCode(x+65), x+1], 0); //=> [A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z]
  • 41. var range = function(i, count) { return unfold(x => if(x <= count) [x, x+1], i); } range(5,10) //=> [ 5, 6, 7, 8, 9, 10 ]
  • 42. var tree = Node(Node(Leaf(2), 1, Leaf(3)), 0, Leaf(4)) fold((acc, x) => acc + x, 0, tree) //=> 10 var clicks = $("#red-button").asEventStream("click") fold((acc, el) => acc.append(el.id), $("#clicklog"), clicks) //=> <div id=“clicklog”/> var us = { “391": "keith@suburban", “52": “kaseem@funny.net" } fold((acc, addr) => acc.cc(addr), Email.create(), us) //=> Email
  • 43.
  • 44. Cons(3, Cons(4, Cons(5, Nil))); tail3 tail4 tail5 Nil Linked List
  • 45. var Nil = {} var _Cons = function(h, tl) { this.head = h; this.tail = tl; }; var Cons = function(h, tl) { return new _Cons(h, tl) } var lst = Cons(3, Cons(4, Cons(5, Nil)));
  • 46. 1 Node(Node(Leaf(2), 1, Leaf(3)), 0, Leaf(4)) 2 3 64 5 7 Tree
  • 47. var Empty = {} var _Leaf = function(x) { this.x = x; } var Leaf = function(x) { return new _Leaf(x) } var _Node = function(l, x, r) { this.left = l; this.x = x; this.right = r; } var Node = function(l, x, r) { return new _Node(l, x, r) }
  • 49. var map = function(f, xs) { return reduce((acc, x) => concat(acc, f(x)), [], xs) }
  • 50. var map = function(f, xs) { return reduce((acc, x) => concat(acc, f(x)), [], xs) } Accumulation Transformation Iteration
  • 51. var map = function(f, xs) { return reduce((acc, x) => concat(acc, f(x)), [], xs) }
  • 52. var mapper = function(f) { return (acc, x) => concat(acc, f(x)) } reduce(mapper(x => x + 1), [], [1,2,3]) //=> [2,3,4]
  • 53. var mapper = function(f) { return (acc, x) => concat(acc, f(x)) } reduce(mapper(x => x + 1), [], [1,2,3]) //=> [2,3,4]
  • 54. var mapper = function(f, cnct) { return (acc, x) => cnct(acc, f(x)) } reduce(mapper(x => x + 1, concat), [], [1,2,3]) //=> [2,3,4]
  • 55. var mapper = function(f, cnct) { return (acc, x) => cnct(acc, f(x)) } reduce(mapper(x => x + 1, concat), [], [1,2,3]) //=> [2,3,4]
  • 56. var filterer = function(f, cnct) { return (acc, x) => f(x) ? cnct(acc, x) : acc } reduce(filterer(x => x > 1, concat), [], [1,2,3]) //=> [2,3]
  • 57. var filterer = function(f, cnct) { return (acc, x) => f(x) ? cnct(acc, x) : acc } reduce(filterer(x => x > 1, concat), [], [1,2,3]) //=> [2,3]
  • 58. var filterer = function(f, cnct) { return (acc, x) => f(x) ? cnct(acc, x) : acc } reduce(filterer(x => x > 1, concat), [], [1,2,3]) //=> [2,3]
  • 59. var copy = function(xs) { return reduce(concat, [], xs) }
  • 60. filterer(x => x > 1, mapper(x => x + 1, concat)) //=> (acc, x) => x > 1 ? concat(acc, f(x)) : acc
  • 61.
  • 62. filterer(x => x > 1, mapper(x => x + 1, concat)) //=> (acc, x) => x > 1 ? concat(acc, f(x)) : acc
  • 63. reduce(filterer(x => x > 1, mapper(x => x + 1, concat)), [], [1,2,3]) //=> [3,4]
  • 64. reduce(filterer(x => x > 1, mapper(x => x + 1, concat)), [], [1,2,3]) //=> [3,4]
  • 65. reduce(filterer(x => x > 1, mapper(x => x + 1, concat)), [], [1,2,3]) //=> [3,4]
  • 66. reduce(filterer(x => x > 1, mapper(x => x + 1, append)), Nil, Cons(1, Cons(2, Cons(3, Nil)))) //=> [3,4]
  • 67. reduce(filterer(x => x > 1, mapper(x => x + 1, append)), Nil, Cons(1, Cons(2, Cons(3, Nil)))) //=> [3,4]
  • 68. reduce(filterer(x => x > 1, mapper(x => x + 1, insert)), Empty, Node(Node(Leaf(2), 1, Leaf(3)), 0, Leaf(4))) //=> [3,4]
  • 69. reduce(filterer(x => x > 1, mapper(x => x + 1, insert)), Empty, Node(Node(Leaf(2), 1, Leaf(3)), 0, Leaf(4))) //=> [3,4]
  • 72. // left identity concat([], xs) == xs // right identity concat(xs, []) == xs // associativity concat(concat(xs, ys), zs) == concat(xs, concat(ys, zs))
  • 73.
  • 74. var sum = function(xs) { return reduce((acc, x) => acc + x, 0, xs) }
  • 75. var _Sum = function(x) { this.val = x } var Sum = function(x){ return new _Sum(x) }
  • 76. _Sum.prototype.concat = function(y){ return Sum(this.val + y.val) } _Sum.prototype.empty = function(){ return Sum(0) } var sum = function(xs) { return reduce((acc, x) => acc + x, 0, xs) }
  • 77. _Sum.prototype.concat = function(y){ return Sum(this.val + y.val) } _Sum.prototype.empty = function(){ return Sum(0) } var sum = function(xs) { return reduce((acc, x) => acc + x, 0, xs) }
  • 78. fold([Sum(1), Sum(2), Sum(3), Sum(4)]) //=> Sum(10) _Sum.prototype.concat = function(y){ return Sum(this.val + y.val) } _Sum.prototype.empty = function(){ return Sum(0) }
  • 79. fold([Product(1),Product(2),Product(3),Product(4)]) //=> Product(24) _Product.prototype.concat = function(y){ return Product(this.val * y.val) } _Product.prototype.empty = function(){ return Product(1) }
  • 80. fold([Max(11),Max(16),Max(3),Max(9)]) //=> Max(16) _Max.prototype.concat = function(y){ return Max(this.val > y.val ? this.val : y.val) } _Max.prototype.empty = function(){ return Max(-Infinity) }
  • 81. _All.prototype.concat = function(y){ return Any(this.val && y.val) } _All.prototype.empty = function(){ return All(true) } fold([All(false), All(false), All(true), All(false)]) //=> All(false)
  • 82. _Any.prototype.concat = function(y){ return Any(this.val || y.val) } _Any.prototype.empty = function(){ return Any(false) } fold([Any(false), Any(false), Any(true), Any(false)]) //=> Any(true)
  • 84. _Any.prototype.concat = function(y){ return Any(this.val || y.val) } _Any.prototype.empty = function(){ return Any(false) } fold([Any(false), Any(false), Any(true), Any(false)]) //=> Any(true)
  • 85. var foldMap = function(f,xs) { return compose(fold, map(f))(xs); } var sum = function(xs){ return foldMap(Sum, xs).val } var max = function(xs){ return foldMap(Max, xs).val } var any = function(xs){ return foldMap(Any, xs).val }
  • 86. var tree = Node(Node(Leaf(2), 1, Leaf(3)), 2, Leaf(4)) sum(tree) //=> 12 product(tree) //=> 38 max(tree) //=> 4
  • 87. var lst = Cons(true, Cons(false, Cons(true, Nil))) any(lst) //=> true all(lst) //=> false
  • 88.
  • 90. [Sum(a)] -> Sum(a) [Product(a)] -> Product(a) [Max(a)] -> Max(a)
  • 94. var cata = function(f, xs) { return f(xs.map(ys => cata(f,ys))) }
  • 95. var cata = function(f, xs) { return f(xs.map(ys => cata(f,ys))) }
  • 96. var cata = function(f, xs) { return f(xs.map(ys => cata(f,ys))) }
  • 97. Fixed point of a Functor
  • 98. Nil.map = function(f) { return Nil; } _Cons.prototype.map = function(f) { return Cons(this.head, f(this.tail)) }
  • 99.
  • 100. var sum = function(x) { return (x === Nil) ? 0 : x.head + x.tail } var lst = Cons(2, Cons(3, Cons(4, Nil))); cata(sum, lst); //=> 9
  • 101. var sum = function(x) { return (x === Nil) ? 0 : x.head + x.tail } var lst = Cons(2, Cons(3, Cons(4, Nil))); cata(sum, lst); //=> 9 Algebra
  • 102. var sum = function(x) { return (x === Nil) ? 0 : x.head + x.tail } var lst = Cons(2, Cons(3, Cons(4, Nil))); cata(sum, lst); // Nil // Cons(4, 0) // Cons(3, 4) // Cons(2, 7) //=> 9
  • 103. map(x => x + 1, Cons(2, Cons(3, Cons(4, Nil)))) //=> Cons(3, Cons(4, Cons(5, Nil))) var map = function(f, xs) { return cata(x => (x == Nil) ? Nil : Cons(f(x.head), x.tail), xs) }
  • 104. Empty.map = function(f) { return Empty } _Leaf.prototype.map = function(f) { return Leaf(this.x) } _Node.prototype.map = function(f) { return Node(f(this.left), this.x, f(this.right)) }
  • 105. cata(t => switch (t.constructor) { case _Node: return t.left + t.x + t.right; case _Leaf: return t.x; default: 0; }, tr) //=> 10 var tr = Node(Node(Leaf(2), 1, Leaf(3)), 0, Leaf(4))
  • 106. var ana = function(g, a) { return g(a).map(x => ana(g,x)) }
  • 107. var ana = function(g, a) { return g(a).map(x => ana(g,x)) }
  • 108. var arrToList = function(xs) { return xs.length === 0 ? Nil : Cons(first(xs), rest(xs)) } ana(arrToList, [1,2,3,4,5]) //=> Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Nil))))) CoAlgebra
  • 109. var arrToList = function(xs) { return xs.length === 0 ? Nil : Cons(first(xs), rest(xs)) } ana(arrToList, [1,2,3,4,5]) //=> Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Nil)))))
  • 111. var arrToList = function(xs) { return xs.length === 0 ? Nil : Cons(first(xs), rest(xs)) } ana(arrToList, [1,2,3,4,5]) //=> Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Nil)))))
  • 112. var makeAlphabet = function(x) { if(x > 25) return Nil; return Cons(String.fromCharCode(x+65), x+1); } ana(makeAlphabet, 0) //=> Cons(A, Cons(B, Cons(C, Cons(D, Cons(E, Cons(F, Cons(G, Cons(H
  • 113. var range = function(acc, count) { return ana(x => (x >= count) ? Nil : Cons(x, x+1), acc) } range(2, 10) //=> Cons(2, Cons(3, Cons(4, Cons(5, Cons(6, Cons(7, Cons(8, Cons(9, Nil))))))))
  • 115.
  • 117.
  • 119. var _Const = function(val) { this.val = val } var Const = function(x) { return new _Const(x) } var _Add = function(x, y) { this.x = x; this.y = y; } var Add = function(x, y) { return new _Add(x, y) } var _Mul = function(x, y) { this.x = x this.y = y } var Mul = function(x, y) { return new _Mul(x, y) }
  • 120. _Const.prototype.map = function(f) { return this } _Add.prototype.map = function(f) { return Add(f(this.x), f(this.y)) } _Mul.prototype.map = function(f) { return Mul(f(this.x), f(this.y)) }
  • 121. var interpret = function(a) { switch(a.constructor) { case _Mul: return a.x * a.y; case _Add: return a.x + a.y; case _Const: return a.val; } } var program = Mul(Add(Const(2), Const(3)), Const(4)) cata(interpret, program); //=> 20
  • 122. var _Concat = function(v, next) { this.val = v; this.next = next; } var Concat = function(v, x){ return new _Concat(v, x) } var _Replace = function(v, x, next) { this.val = v; this.x = x; this.next = next; } var Replace = function(v, x, nt){ return new _Replace(v, x, nt) } var _Input = function(v) { this.val = v } var Input = function(v){ return new _Input(v) }
  • 123. _Concat.prototype.map = function(f) { return Concat(this.val, f(this.next)) } _Replace.prototype.map = function(f) { return Replace(this.val, this.x, f(this.next)) } _Input.prototype.map = function(f) { return Input(this.val) }
  • 124. var interpret = function(t) { switch (t.constructor) { case _Concat: return t.next.concat(t.val); case _Replace: return t.next.replace(t.val, t.x); case _Input: return t.val; } } var prog = Concat("world", Replace("h", "m", Input(“hello"))) cata(interpret, prog) //=> melloworld
  • 125. var interpret1 = function(t) { switch (t.constructor) { case _Concat: return "concatting “+t.val+" after "+t.next; case _Replace: return "replacing "+t.val+" with "+t.x+" on "+t.next; case _Input: return t.val; } } var prog = Concat("world", Replace("h", "m", Input(“hello"))) cata(interpret1, prog) //=> concatting world after replacing h with m on hello
  • 127.
  • 128.