ebook img

Professor Frisby's Mostly Adequate Guide To Functional Programming PDF

2015·2.2 MB·English
Save to my drive
Quick download
Download
Most books are stored in the elastic cloud where traffic is expensive. For this reason, we have a limit on daily download.

Preview Professor Frisby's Mostly Adequate Guide To Functional Programming

mostly-adequate-guide Table of Contents 1. Introduction 2. Chapter 1: What ever are we doing? i. Introductions ii. A brief encounter 3. Chapter 2: First Class Functions i. A quick review ii. Why favor first class? 4. Chapter 3: Pure Happiness with Pure Functions i. Oh to be pure again ii. Side effects may include... iii. 8th grade math iv. The case for purity v. In Summary 5. Chapter 4: Currying i. Can't live if livin' is without you ii. More than a pun / Special sauce iii. In Summary 6. Chapter 5: Coding by Composing i. Functional Husbandry ii. Pointfree iii. Debugging iv. Category Theory v. In Summary 7. Chapter 6: Example Application i. Declarative Coding ii. A flickr of functional programming iii. A Principled Refactor iv. In Summary 8. Chapter 7: Hindley-Milner and Me i. What's your type? ii. Tales from the cryptic iii. Narrowing the possibility iv. Free as in theorem v. In Summary 9. Chapter 8: Tupperware i. The Mighty Container ii. My First Functor iii. Schrödinger’s Maybe iv. Pure Error Handling v. Old McDonald had Effects… vi. Asynchronous Tasks vii. A Spot of Theory viii. In Summary 10. Chapter 9: Monadic Onions i. Pointy Functor Factory ii. Mixing Metaphors iii. My chain hits my chest iv. Theory v. In Summary 2 mostly-adequate-guide 11. Chapter 10: Applicative Functors i. Applying Applicatives ii. Ships in bottles iii. Coordination Motivation iv. Bro, do you even lift? v. Free can openers vi. Laws vii. In Summary 3 mostly-adequate-guide About this book This is a book on the functional paradigm in general. We'll use the world's most popular functional programming language: JavaScript. Some may feel this is a poor choice as it's against the grain of the current culture which, at the moment, feels predominately imperative. However, I believe it is the best way to learn FP for several reasons: You likely use it every day at work. This makes it possible to practice and apply your acquired knowledge each day on real world programs rather than pet projects on nights and weekends in an esoteric FP language. We don't have to learn everything up front to start writing programs. In a pure functional language, you cannot log a variable or read a DOM node without using monads. Here we can cheat a little as we learn to purify our codebase. It's also easier to get started in this language since it's mixed paradigm and you can fall back on your current practices while there are gaps in your knowledge. Introduction 4 mostly-adequate-guide The language is fully capable of writing top notch functional code. We have all the features we need to mimic a language like Scala or Haskell with the help of a tiny library or two. Object-oriented programming currently dominates the industry, but it's clearly awkward in JavaScript. It's akin to camping off of a highway or tap dancing in galoshes. We have to bind all over the place lest this change out from under us, we don't have classes(Yet), we have various work arounds for the quirky behavior when the new keyword is forgotten, private members are only available via closures. To a lot of us, FP feels more natural anyways. That said, typed functional languages will, without a doubt, be the best place to code in the style presented by this book. JavaScript will be our means of learning a paradigm, where you apply it is up to you. Luckily, the interfaces are mathematical and, as such, ubiquitous. You'll find yourself at home with swiftz, scalaz, haskell, purescript, and other mathematically inclined environments. Gitbook (for a better reading experience) Read it online Download EPUB Download Mobi (Kindle) Do it yourself git clone https://github.com/DrBoolean/mostly-adequate-guide.git cd mostly-adequate-guide/ npm install gitbook-cli -g gitbook init brew update brew cask install calibre gitbook mobi . ./functional.mobi Table of Contents See SUMMARY.md Contributing See CONTRIBUTING.md Translations See TRANSLATIONS.md Plans for the future Part 1 is a guide to the basics. I'm updating as I find errors since this is the initial draft. Feel free to help! Part 2 will address type classes like functors and monads all the way through to traversable. I hope to squeeze in transformers and a pure application. Part 3 will start to dance the fine line between practical programming and academic absurdity. We'll look at comonads, f-algebras, free monads, yoneda, and other categorical constructs. Introduction 5 mostly-adequate-guide Chapter 1: What ever are we doing? Introductions Hi I'm Professor Franklin Risby, pleased to make your acquaintance. We'll be spending some time together as I'm supposed to teach you a bit about functional programming. But enough about me, what about you? I'm hoping you're familiar with the JavaScript language, have a teensy bit of Object-Oriented experience, and fancy yourself a working class programmer. You don't need to have a Ph.D in Entomology, you just need to know how to find and kill some bugs. I won't assume any previous functional programming knowledge because we both know what happens when you assume, but I will expect you to have run into some of the unfavorable situations that arise from working with mutable state, unrestricted side effects, and unprincipled design. Now that we've been properly introduced, let's get on with it. The purpose of this chapter is to give you a feel for what we're after when we write functional programs. We must have some idea about what makes a program functional or we'll find ourselves scribbling aimlessly, avoiding objects at all costs - a clumsy endeavor indeed. We need a bullseye to hurl our code toward, some celestial compass for when the waters get rough. Now there are some general programming principles, various acronymic credos that guide us through the dark tunnels of any application: DRY (don't repeat yourself), loose coupling high cohesion, YAGNI (ya ain't gonna need it), principle of least surprise, single responsibility, and so on. I won't belabor listing each and every guideline I've heard throughout the years... the point is that they hold up in a functional setting, though they're merely tangential to our goal. What I'd like you to get a feel for now, before we get any further, is our intention when we poke and prod at the keyboard; our functional Xanadu. A brief encounter Let's start with a touch of insanity. Here is a seagull application. When flocks conjoin they become a larger flock and when they breed they increase by the number of seagulls with whom they're breeding. Now this is not intended to be good Object-Oriented code, mind you, it is here to highlight the perils of our modern, assignment based approach. Behold: var Flock = function(n) { this.seagulls = n; }; Flock.prototype.conjoin = function(other) { this.seagulls += other.seagulls; return this; }; Flock.prototype.breed = function(other) { this.seagulls = this.seagulls * other.seagulls; return this; }; var flock_a = new Flock(4); var flock_b = new Flock(2); var flock_c = new Flock(0); var result = flock_a.conjoin(flock_c) .breed(flock_b).conjoin(flock_a.breed(flock_b)).seagulls; //=> 32 Who on earth would craft such a ghastly abomination? It is unreasonably difficult to keep track of the mutating internal Chapter 1: What ever are we doing? 6 mostly-adequate-guide state. And, good heavens, the answer is even incorrect! It should have been 16 , but flock_a wound up permanently altered in the process. Poor flock_a . This is anarchy in the I.T.! This is wild animal arithmetic! If you don't understand this program, it's okay, neither do I. The point is that state and mutable values are hard to follow even in such a small example. Let's try again with a more functional approach: var conjoin = function(flock_x, flock_y) { return flock_x + flock_y }; var breed = function(flock_x, flock_y) { return flock_x * flock_y }; var flock_a = 4; var flock_b = 2; var flock_c = 0; var result = conjoin( breed(flock_b, conjoin(flock_a, flock_c)), breed(flock_a, flock_b) ); //=>16 Well, we got the right answer this time. There's much less code. The function nesting is a tad confusing...(we'll remedy this situation in ch5). It's better, but let's dig deeper. There are benefits to calling a spade a spade. Had we done so, we might have seen we're just working with simple addition ( conjoin ) and multiplication ( breed ). There's really nothing special at all about these two functions other than their names. Let's rename our custom functions to reveal their true identity. var add = function(x, y) { return x + y }; var multiply = function(x, y) { return x * y }; var flock_a = 4; var flock_b = 2; var flock_c = 0; var result = add( multiply(flock_b, add(flock_a, flock_c)), multiply(flock_a, flock_b) ); //=>16 And with that, we gain the knowledge of the ancients: // associative add(add(x, y), z) == add(x, add(y, z)); // commutative add(x, y) == add(y, x); // identity add(x, 0) == x; // distributive multiply(x, add(y,z)) == add(multiply(x, y), multiply(x, z)); Ah yes, those old faithful mathematical properties should come in handy. Don't worry if you didn't know them right off the top of your head. For a lot of us, it's been a while since we've reviewed this information. Let's see if we can use these properties to simplify our little seagull program. // Original line add(multiply(flock_b, add(flock_a, flock_c)), multiply(flock_a, flock_b)); Chapter 1: What ever are we doing? 7 mostly-adequate-guide // Apply the identity property to remove the extra add // (add(flock_a, flock_c) == flock_a) add(multiply(flock_b, flock_a), multiply(flock_a, flock_b)); // Apply distributive property to achieve our result multiply(flock_b, add(flock_a, flock_a)); Brilliant! We didn't have to write a lick of custom code other than our calling function. We include add and multiply definitions here for completeness, but there is really no need to write them - we surely have an add and multiply provided by some previously written library. You may be thinking "how very strawman of you to put such a mathy example up front". Or "real programs are not this simple and cannot be reasoned about in such a way". I've chosen this example because most of us already know about addition and multiplication so it's easy to see how math can be of use to us here. Don't despair, throughout this book, we'll sprinkle in some category theory, set theory, and lambda calculus to write real world examples that achieve the same simplicity and results as our flock of seagulls example. You needn't be a mathematician either, it will feel just like using a normal framework or api. It may come as a surprise to hear that we can write full, everyday applications along the lines of the functional analog above. Programs that have sound properties. Programs that are terse, yet easy to reason about. Programs that don't reinvent the wheel at every turn. Lawlessness is good if you're a criminal, but in this book, we'll want to acknowledge and obey the laws of math. We'll want to use the theory where every piece tends to fit together so politely. We'll want to represent our specific problem in terms of generic, composable bits and then exploit their properties for our own selfish benefit. It will take a bit more discipline than the "anything goes" approach of imperative(We'll go over the precise definition of imperative later in the book, but for now it's anything other than functional programming) programming, but the payoff of working within a principled, mathematical framework will astound you. We've seen a flicker of our functional north star, but there are a few concrete concepts to grasp before we can really begin our journey. Chapter 2: First Class Functions Chapter 1: What ever are we doing? 8 mostly-adequate-guide Chapter 2: First Class Functions A quick review When we say functions are "first class", we mean they are just like everyone else... so normal class(coach?). We can treat functions like any other data type and there is nothing particularly special about them - store them in arrays, pass them around, assign them to variables, what have you. That is JavaScript 101, but worth a mention as a quick code search on github will show the collective evasion, or perhaps widespread ignorance of the concept. Shall we go for a feigned example? We shall. var hi = function(name){ return "Hi " + name; }; var greeting = function(name) { return hi(name); }; Here, the function wrapper around hi in greeting is completely redundant. Why? Because functions are callable in JavaScript. When hi has the () at the end it will run and return a value. When it does not, it simply returns the function stored in the variable. Just to be sure, have a look-see: hi; // function(name){ // return "Hi " + name // } hi("jonas"); // "Hi jonas" Since greeting is merely turning around and calling hi with the very same argument, we could simply write: var greeting = hi; greeting("times"); // "Hi times" In other words, hi is already a function that expects one argument, why place another function around it that simply calls hi with the same bloody argument? It doesn't make any damn sense. It's like donning your heaviest parka in the dead of July just to blast the air and demand an ice lolly. It is obnoxiously verbose and, as it happens, bad practice to surround a function with another function merely to delay evaluation. (We'll see why in a moment, but it has to do with maintenance.) A solid understanding of this is critical before moving on, so let's see a few more fun examples excavated from npm modules. // ignorant var getServerStuff = function(callback){ return ajaxCall(function(json){ return callback(json); Chapter 2: First Class Functions 9 mostly-adequate-guide }); }; // enlightened var getServerStuff = ajaxCall; The world is littered with ajax code exactly like this. Here is the reason both are equivalent: // this line return ajaxCall(function(json){ return callback(json); }); // is the same as this line return ajaxCall(callback); // so refactor getServerStuff var getServerStuff = function(callback){ return ajaxCall(callback); }; // ...which is equivalent to this var getServerStuff = ajaxCall; // <-- look mum, no ()'s And that, folks, is how it is done. Once more then we'll see why I'm so insistent. var BlogController = (function() { var index = function(posts) { return Views.index(posts); }; var show = function(post) { return Views.show(post); }; var create = function(attrs) { return Db.create(attrs); }; var update = function(post, attrs) { return Db.update(post, attrs); }; var destroy = function(post) { return Db.destroy(post); }; return { index: index, show: show, create: create, update: update, destroy: destroy }; })(); This ridiculous controller is 99% fluff. We could either rewrite it as: var BlogController = { index: Views.index, show: Views.show, create: Db.create, update: Db.update, destroy: Db.destroy }; ...or scrap it altogether as it does nothing other than bundle our Views and Db together. Chapter 2: First Class Functions 10

See more

The list of books you might like

Most books are stored in the elastic cloud where traffic is expensive. For this reason, we have a limit on daily download.