Download - Fact, Fiction, and FP
![Page 1: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/1.jpg)
![Page 2: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/2.jpg)
• Lots of functional JavaScript code
• Benefits and drawbacks
• Functional Optimizations
• Lots of unexplained type signatures
You will see
![Page 3: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/3.jpg)
• Detailed explanations of the code
• Definitions for functional constructs
• Extensive performance analysis
You won’t see
![Page 4: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/4.jpg)
![Page 5: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/5.jpg)
59 // src :: FlickrItem -> URL 60 var src = compose(_.get('m'), _.get('media')); 61 62 // srcs :: FlickrSearch -> [URL] 63 var srcs = compose(map(src), _.get('items')); 64 65 // images :: FlickrSearch -> [DOM] 66 var images = compose(map(imageTag), srcs); 67 68 // tags :: FlickrSearch -> [DOM] 69 var tags = compose(toP, _.countBy(_.id), _.filter(_.isEmpty), chain(split(‘ ‘))); 70 71 // imagesAndTags :: Tuple [DOM] [DOM] 72 var imagesAndTags = liftA2(Tuple, images, tags); 73 74 // widget :: String -> PictureBox 75 var widget = compose(PictureBox, map(imagesAndTags), getJSON, url); 76 77 /////////////////////////////////////////////////////////////////////////////////// 78 79 mconcat([widget('cats'), widget('dogs')]).fork(log, function(x){ 80 compose(setHtml($('#flickr')), _.first)(x) 81 compose(setHtml($(‘#tag_cloud')), _.last)(x) 82 }); 83 });
![Page 6: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/6.jpg)
![Page 7: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/7.jpg)
No matter what language you work in, programming in a functional style provides benefits. You should do it whenever it is convenient, and you should think hard about the decision when it isn't convenient.
![Page 8: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/8.jpg)
Questions
• Why might one do this?
• What problems are there?
• Is it performant?
• Is it “production ready?”
![Page 9: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/9.jpg)
Pointfree
![Page 10: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/10.jpg)
var replace = curry(function(regex, x, replaceable) { return replaceable.replace(regex, x);});
var squish = replace(/\s+/g, '');
squish("I like to move it move it"); // Iliketomoveitmoveit
We can curry
![Page 11: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/11.jpg)
var wackyText = compose(capitalize, reverse, squish)
wackyText(“turtle power") // Rewopeltrut
We can compose
![Page 12: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/12.jpg)
Pointfree
var clientApp = compose(render, doThings, httpGet(‘/posts'))
var serverApp = compose(sendJSON, doThings, Db.all(‘posts’))
var shellApp = compose(display, doThings, prompt("what's up?"))
![Page 13: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/13.jpg)
![Page 14: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/14.jpg)
![Page 15: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/15.jpg)
![Page 16: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/16.jpg)
httpGet('/post/2', function(json){ renderPost(json);});
Pointfree
![Page 17: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/17.jpg)
httpGet('/post/2', function(json, err){ renderPost(json, err);});
Pointfree
![Page 18: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/18.jpg)
httpGet(‘/post/2’, renderPost)
Pointfree
![Page 19: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/19.jpg)
httpGet(‘/post/2’, renderPost)
Pointfree
GOOD
![Page 20: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/20.jpg)
![Page 21: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/21.jpg)
Pointfree
var goodArticles = function(articles) { return _.filter(articles, function(article){ return _.isDefined(article); })}
![Page 22: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/22.jpg)
Pointfree
var goodArticles = function(articles) { return _.filter(articles, function(article){ return _.isDefined(article); })}
var goodArticles = filter(isDefined)
![Page 23: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/23.jpg)
Pointfree
var goodArticles = function(articles) { return _.filter(articles, function(article){ return _.isDefined(article); })}
var goodArticles = filter(isDefined)
![Page 24: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/24.jpg)
Pointfree
var goodArticles = function(articles) { return _.filter(articles, function(article){ return _.isDefined(article); })}
var goodArticles = filter(isDefined)
GOOD
![Page 25: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/25.jpg)
Pointfree
var getChildren = function(el) { return el.childNodes;}
var getAllChildren = function(els) { return _.map(els, function(el) { return getChildren(el); });}
![Page 26: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/26.jpg)
Pointfree
var getChildren = function(el) { return el.childNodes;}
var getAllChildren = function(els) { return _.map(els, function(el) { return getChildren(el); });}
var getChildren = get('childNodes')var getAllChildren = map(getChildren)
![Page 27: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/27.jpg)
Pointfree
var getChildren = function(el) { return el.childNodes;}
var getAllChildren = function(els) { return _.map(els, function(el) { return getChildren(el); });}
var getChildren = get('childNodes')var getAllChildren = map(getChildren)
![Page 28: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/28.jpg)
Pointfree
var getChildren = function(el) { return el.childNodes;}
var getAllChildren = function(els) { return _.map(els, function(el) { return getChildren(el); });}
var getChildren = get('childNodes')var getAllChildren = map(getChildren)
GOOD
![Page 29: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/29.jpg)
![Page 30: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/30.jpg)
Pointfree
var grandChildren = function(selector) { var el = document.querySelector(selector); var children = getChildren(el); return map(getChildren, children);}
var grandChildren = compose( map(getChildren) , getChildren , document.querySelector )
![Page 31: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/31.jpg)
Pointfree
var grandChildren = function(selector) { var el = document.querySelector(selector); var children = getChildren(el); return map(getChildren, children);}
var grandChildren = compose( map(getChildren) , getChildren , document.querySelector )
GOOD
![Page 32: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/32.jpg)
![Page 33: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/33.jpg)
Pointfree
var video = { src: 'http://youtube.com?v=23423' , description: 'family matters ep1' , screenshots: [ { url: 'i.ytimg.com/OrIxGlo.webp', size: ‘120x120' } , { url: 'i.ytimg.com/3rAxRdb.webp', size: ‘1020x764' } ] }
var thumb = compose(_.first, _.get(‘screenshots'))
var thumbUrl = compose(_.get('url'), thumb)
var thumbWithHost = compose(concat('http://youtube.com'), thumbUrl)
thumbWithHost(video)// http://youtube.com/i.ytimg.com/OrIxaBJ9Glo.webp
![Page 34: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/34.jpg)
Pointfree
var video = { src: 'http://youtube.com?v=23423' , description: 'family matters ep1' , screenshots: [ { url: 'i.ytimg.com/OrIxGlo.webp', size: ‘120x120' } , { url: 'i.ytimg.com/3rAxRdb.webp', size: ‘1020x764' } ] }
var thumbUrl = compose(_.get('url'), thumb)
var thumb = compose(_.first, _.get(‘screenshots'))
var thumbWithHost = compose(concat('http://youtube.com'), thumbUrl)
thumbWithHost(video)// TypeError
![Page 35: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/35.jpg)
Pointfree
var video = { src: 'http://youtube.com?v=23423' , description: 'family matters ep1' , screenshots: [ { url: 'i.ytimg.com/OrIxGlo.webp', size: ‘120x120' } , { url: 'i.ytimg.com/3rAxRdb.webp', size: ‘1020x764' } ] }
var thumbUrl = compose(_.get('url'), thumb)
var thumb = compose(_.first, _.get(‘screenshots'))
var thumbWithHost = compose(concat('http://youtube.com'), thumbUrl)
thumbWithHost(video)// TypeError
Meh
![Page 36: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/36.jpg)
![Page 37: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/37.jpg)
![Page 38: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/38.jpg)
![Page 39: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/39.jpg)
First Class?
["10", "50", "20"].map(function(x){ return parseInt(x); });// [10, 50, 20]
["10", "50", "20"].map(parseInt);// [10, NaN, NaN]
![Page 40: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/40.jpg)
First Class?
["10", "50", "20"].map(function(x){ return parseInt(x); });// [10, 50, 20]
["10", "50", "20"].map(parseInt);// [10, NaN, NaN]
// "The Madness of King JavaScript" by Reg Braithwaite (raganwald)
BAD
![Page 41: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/41.jpg)
First Class?
var phone = { dial: function(x){ console.log("DIALING: ", this.format(x)); }, format: function(n) { return n.replace(/-/g, '') }};
var numbers = ["234-3535-2342", “1-653-124-8321"];
numbers.map(function(x){ return phone.dial(x); });// DIALING: 23435352342// DIALING: 16531248321
![Page 42: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/42.jpg)
First Class?
var phone = { dial: function(x){ console.log("DIALING: ", this.format(x)); }, format: function(n) { return n.replace(/-/g, '') }};
var numbers = ["234-3535-2342", “1-653-124-8321"];
numbers.map(function(x){ return phone.dial(x); });// DIALING: 23435352342// DIALING: 16531248321
numbers.map(phone.dial);
![Page 43: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/43.jpg)
First Class?
var phone = { dial: function(x){ console.log("DIALING: ", this.format(x)); }, format: function(n) { return n.replace(/-/g, '') }};
var numbers = ["234-3535-2342", “1-653-124-8321"];
numbers.map(function(x){ return phone.dial(x); });// DIALING: 23435352342// DIALING: 16531248321
numbers.map(phone.dial);// TypeError: Object #<Object> has no method 'format'
![Page 44: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/44.jpg)
First Class?
var phone = { dial: function(x){ console.log("DIALING: ", this.format(x)); }, format: function(n) { return n.replace(/-/g, '') }};
var numbers = ["234-3535-2342", “1-653-124-8321"];
numbers.map(function(x){ return phone.dial(x); });// DIALING: 23435352342// DIALING: 16531248321
numbers.map(phone.dial.bind(phone));// DIALING: 23435352342// DIALING: 16531248321
![Page 45: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/45.jpg)
First Class?
var phone = { dial: function(x){ console.log("DIALING: ", this.format(x)); }, format: function(n) { return n.replace(/-/g, '') }};
var numbers = ["234-3535-2342", “1-653-124-8321"];
numbers.map(function(x){ return phone.dial(x); });// DIALING: 23435352342// DIALING: 16531248321
numbers.map(phone.dial.bind(phone));// DIALING: 23435352342// DIALING: 16531248321
BAD
![Page 46: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/46.jpg)
![Page 47: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/47.jpg)
//+ render :: [Tag] -> DOMvar render = compose($(‘#tag-cloud').html, tagView, addFontSizes)
//+ tagCloud :: Params -> Future(DOM)var tagCloud = compose(map(render), httpGet('/tags'))
![Page 48: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/48.jpg)
//+ setHtml :: String -> Html -> IO(DOM)var setHtml = curry(function(selector, h) { return IO(function() { return $(selector).html(h); });});
//+ render :: [Tag] -> IO(DOM)var render = compose(setHtml(‘#tag-cloud'), tagView, addFontSizes)
//+ tagCloud :: Params -> Future(IO(DOM))var tagCloud = compose(map(render), httpGet('/tags'))
![Page 49: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/49.jpg)
![Page 50: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/50.jpg)
![Page 51: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/51.jpg)
Pointfree
• Removes unnecessary code
• High level declarative apps
• Encourages generic code
• Encourages purity
![Page 52: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/52.jpg)
Pointfree
• Order of definition matters
• Weird interop with imperative community (impure, swiss army fn’s, & ‘this’)
![Page 53: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/53.jpg)
![Page 54: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/54.jpg)
![Page 55: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/55.jpg)
![Page 56: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/56.jpg)
![Page 57: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/57.jpg)
![Page 58: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/58.jpg)
Demos
![Page 59: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/59.jpg)
Typeclass
![Page 60: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/60.jpg)
Typeclass
promise.then(function(x){ return x + 1 }); // Promise(2)
[1].map(function(x) { return x + 1 }); // [2]
event_stream.subscribe(function(x) { return x + 1 }) // EventStream(2)
![Page 61: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/61.jpg)
![Page 62: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/62.jpg)
var Container = function(val) { this.val = val;}
Container.prototype.of = function(x) { return new Container(x);}
Container.prototype.chain = function(f) { return f(this.val);};
Typeclass
![Page 63: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/63.jpg)
Typeclass
(a -> b) -> M(a) -> M(b)
We can map over them
![Page 64: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/64.jpg)
Typeclass
(a -> b) -> M(a) -> M(b)
We can map over them
promise.map(function(x){ return x + 1 }); // Promise(2)
[1].map(function(x) { return x + 1 }); // [2]
event_stream.map(function(x) { return x + 1 }) // EventStream(2)
Just(1).map(function(x) { return x + 1 }) // Just(2)
Nothing.map(function(x) { return x + 1 }) // Nothing
IO(1).map(function(x) { return x + 1 }) // IO(2)
![Page 65: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/65.jpg)
Typeclass
M(M(a)) -> M(a)
We can flatten/un-nest them
![Page 66: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/66.jpg)
Typeclass
M(M(a)) -> M(a)
We can flatten/un-nest them
[['hello']] -> ['hello']
Just(Just(true)) -> Just(true)
![Page 67: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/67.jpg)
Typeclass
M(a -> b) -> M(a) -> M(b)
We can apply functions within them
![Page 68: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/68.jpg)
Typeclass
M(a -> b) -> M(a) -> M(b)
We can apply functions within them
var finished = curry(function(click, anim) { alert(“Finished!"); });
EventStream.of(finished).ap(button_clicks).ap(animation_done);
![Page 69: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/69.jpg)
Typeclass
M(a) -> M(a) -> M(a)
We can combine them
![Page 70: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/70.jpg)
Typeclass
M(a) -> M(a) -> M(a)
We can combine them
Api.get(‘/unstarred’).concat(Api.get('/starred'))
// Future([Item])
![Page 71: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/71.jpg)
Typeclass
M(N(a)) -> MN(a)
We can compose them
![Page 72: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/72.jpg)
Typeclass
M(N(a)) -> MN(a)
We can compose them
//+ askQuestion :: IO(Maybe(String))compose(map(map(storeResponse)), askQuestion)
//+ askQuestion :: Compose(IO(Maybe(String)))compose(map(storeResponse), Compose, askQuestion)
![Page 73: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/73.jpg)
Typeclass
M(N(a)) -> N(M(a))
We can commute them
![Page 74: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/74.jpg)
Typeclass
M(N(a)) -> N(M(a))
We can commute them
compose(sequenceA, map(readFile))
// Future([String])
![Page 75: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/75.jpg)
Typeclass
We can derive lots of this!
derive(MyType, [Functor, Applicative, Foldable])
*https://github.com/fantasyland/fantasy-land/pull/66
![Page 76: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/76.jpg)
![Page 77: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/77.jpg)
![Page 78: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/78.jpg)
Typeclass
//+ validate :: UserAttrs -> Either([Error], UserAttrs)//+ saveUser :: UserAttrs -> Future(User)//+ emailPassword :: User -> Future(Email)
//+ saveThenEmail :: UserAttrs -> Future(Email)var saveThenEmail = compose(chain(emailPassword), saveUser)
//+ createUser :: UserAttrs -> Either([Error], Future(Email))var createUser = compose(map(saveThenEmail), validate)
![Page 79: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/79.jpg)
Typeclass
//+ validate :: UserAttrs -> Either([Error], UserAttrs)//+ saveUser :: UserAttrs -> Future(User)//+ emailPassword :: User -> Future(Email)
//+ saveThenEmail :: UserAttrs -> Future(Email)var saveThenEmail = compose(chain(emailPassword), saveUser)
//+ createUser :: UserAttrs -> Either([Error], Future(Email))var createUser = compose(map(saveThenEmail), validate)
GOOD
![Page 80: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/80.jpg)
![Page 81: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/81.jpg)
![Page 82: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/82.jpg)
![Page 83: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/83.jpg)
GOOD
![Page 84: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/84.jpg)
![Page 85: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/85.jpg)
Typeclass
//+ lookup :: String -> {String: a} -> a|nullvar lookup = curry(function(x, obj) { return obj[x];})
var upperName = compose(toUpperCase, lookup(‘name'))
upperName({name: “Tori Amos"}) // “TORI AMOS”
upperName({first_name: "Tori", last_name: “Spelling"}) // BOOM!
![Page 86: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/86.jpg)
Typeclass
//+ safeLookup :: String -> {String: a} -> Maybe(a)var safeLookup = curry(function(x, obj) { return Maybe.fromNullable(obj[x]);});
var upperName = compose(map(toUpperCase), safeLookup(‘name'))
upperName({name: “Tori Amos”})// Just(“TORI AMOS”)
upperName({first_name: "Tori", last_name: “Spelling”})// Nothing
![Page 87: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/87.jpg)
Typeclass
//+ safeLookup :: String -> {String: a} -> Maybe(a)var safeLookup = curry(function(x, obj) { return Maybe.fromNullable(obj[x]);});
var upperName = compose(map(toUpperCase), safeLookup(‘name'))
upperName({name: “Tori Amos”})// Just(“TORI AMOS”)
upperName({first_name: "Tori", last_name: “Spelling”})// Nothing
GOOD
![Page 88: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/88.jpg)
![Page 89: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/89.jpg)
GOOD
![Page 90: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/90.jpg)
![Page 91: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/91.jpg)
Typeclass
//+ readFile :: Future(Maybe(String))
//+ lipogram :: String -> Future(Maybe(String))var lipogram = compose(map(map(replace(/e/ig))), readFile);
![Page 92: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/92.jpg)
Typeclass
//+ readFile :: String -> Compose(Future(Maybe(String)))var readFile = compose(Compose, _readFile)
//+ lipogram :: String -> Compose(Future(Maybe(String)))var lipogram = compose(map(replace(/e/ig)), readFile);
![Page 93: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/93.jpg)
Typeclass
var WebApp = ReaderT(StateT(Future))
![Page 94: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/94.jpg)
Typeclass
Meh
var WebApp = ReaderT(StateT(Future))
![Page 95: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/95.jpg)
![Page 96: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/96.jpg)
Typeclass
do a <- Just 3 b <- Just 1 return a + b
Just(3).chain(function(a) { return Just(1).chain(function(b) { return Maybe.of(a + b); });};
JavaScript
Haskell
![Page 97: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/97.jpg)
Typeclass
do a <- Just 3 b <- Just 1 return a + b
liftM2(add, Just(3), Just(1))JavaScript
Haskell
![Page 98: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/98.jpg)
Typeclass
do post_id <- param "id" post <- lift $ findPost post_id return (toJSON post)
chain(compose(lift, map(toJSON), findPost), param(‘id'))
JavaScript
Haskell
(lift . (fmap toJSON) . findPost) =<< param "id"
![Page 99: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/99.jpg)
Typeclass
do post_id <- param "id" post <- lift $ findPost post_id return (toJSON post)
chain(compose(lift, map(toJSON), findPost), param(‘id'))
JavaScript
Haskell
(lift . (fmap toJSON) . findPost) =<< param "id"
Meh
![Page 100: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/100.jpg)
![Page 101: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/101.jpg)
Typeclass
do post_id <- param "id" post <- lift $ findPost post_id return (toJSON post)
chain(compose(lift, map(toJSON) findPost), param(‘id'))
JavaScript
Haskell
(lift . (fmap toJSON) . findPost) =<< param "id"
![Page 102: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/102.jpg)
Typeclass
do post_id <- param "id" post <- lift $ findPost post_id return (toJSON post)
chain(compose(WebApp.lift, map(toJSON) findPost), param(‘id'))
JavaScript
Haskell
(lift . (fmap toJSON) . findPost) =<< param "id"
![Page 103: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/103.jpg)
Typeclass
//+ savePhotos :: [Path] -> Future([Photo])var savePhotos = compose(traverse(uploadPhoto), map(toBlob))
//+ gift :: Future(User) -> Maybe(Future(Card))var gift = compose(traverse(sendCard, Maybe.of), map(_.get("birthday"))
![Page 104: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/104.jpg)
Typeclass
//+ savePhotos :: [Path] -> Future([Photo])var savePhotos = compose(traverse(uploadPhoto), map(toBlob))
//+ gift :: Future(User) -> Maybe(Future(Card))var gift = compose(traverse(sendCard, Maybe.of), map(_.get("birthday"))
BAD
![Page 105: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/105.jpg)
Typeclass
• Universal interface (across languages)
• Generic programs/libraries
• Safer programs
• Theory backed
• Intuition
![Page 106: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/106.jpg)
• Missing polymorphic “point”
• Working ‘blind’ with stacked containers
• No syntactic sugar
Typeclass
![Page 107: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/107.jpg)
![Page 108: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/108.jpg)
![Page 109: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/109.jpg)
![Page 110: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/110.jpg)
![Page 111: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/111.jpg)
![Page 112: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/112.jpg)
Demos
![Page 113: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/113.jpg)
![Page 114: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/114.jpg)
![Page 115: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/115.jpg)
Shortcut Fusion
// g :: forall b. (t -> b -> b) -> b -> b
reduce(c, n, build(g)) = g(c, n)
![Page 116: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/116.jpg)
Shortcut Fusion
//build :: (forall b. (a -> b -> b) -> b -> b) -> [a]var build = function(g){ return g(concat, []);}
//+ map :: (a -> b) -> [a] -> [b]var map = curry(function(f, xs){ return build(function(c, n){ return reduce(function(acc, x){ return c(f(x), acc); }, n, xs); });});
![Page 117: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/117.jpg)
Shortcut Fusion
var sum = reduce(add, 0);
var sqr = function(x) {return x * x }
var sumSqs = compose(sum, map(sqr)) // reduce(function(acc, x){ return add(sqr(x), acc) }, 0);
![Page 118: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/118.jpg)
Compile while youcompose
//+ doorman :: [User] -> Uservar doorman = compose(first, filter(gte(21)), map(_.get('age')));
![Page 119: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/119.jpg)
![Page 120: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/120.jpg)
var addTwenty = memoize(function(x) {return x + 20;
})
Memoization
![Page 121: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/121.jpg)
var addTwenty = memoize(function(x) {return x + 20;
})
addTwenty(10) // 30addTwenty(10) // 30 (didn't run)addTwenty(11) // 31
Memoization
![Page 122: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/122.jpg)
Memoization
var getPosts = memoize(function(id) { return new Future(function(rej, res) { $.getJSON('/posts/'+id, res); });});
![Page 123: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/123.jpg)
Memoization
var getPosts = memoize(function(id) { return new Future(function(rej, res) { $.getJSON('/posts/'+id, res); });});
getPosts(2) // FuturegetPosts(2) // Future (didn't run)getPosts(3) // Future
![Page 124: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/124.jpg)
Memoization
var pQuery = $.toIO()
pQuery(".troll") // IO(function(){ return $(".troll") })
pQuery.runIO() // [Dom, Dom]pQuery.runIO() // [Dom, Dom, Dom]
![Page 125: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/125.jpg)
Parallel code
foldMap(Sum, [2, 3, 5])
![Page 126: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/126.jpg)
Parallel code
liftA3(fn, A1, A2, A3)
![Page 127: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/127.jpg)
Parallel code
var longCalc // Int -> Future(Int)
var collectResults = curry(function(rslt1, rslt2, rslt3){})
liftA3(collectResults, longCalc(20), longCalc(30), longCalc(10))
![Page 128: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/128.jpg)
Parallel code
var hasName // Attrs -> Validation
liftA3(save, hasName, hasEmail, hasPhone)
![Page 129: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/129.jpg)
![Page 130: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/130.jpg)
![Page 131: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/131.jpg)
![Page 132: Fact, Fiction, and FP](https://reader036.vdocuments.us/reader036/viewer/2022062419/5588f4c4d8b42a6c138b4684/html5/thumbnails/132.jpg)
THANKS!@drboolean