Thanks for the opporunity to talk about programming with you all
=<< Welcome to the Talk Called >>=
Wide-Eyed Crazy Functional Programming
=<< What's up with that Title? >>=
A few people asked me about the title, so I thought I'd clear up what it means
=<< What's up with that Title? >>=
It’s functions, pure functions! Pure functions and their values, PURE FUNCTIONS FOREVER AND FOREVER AND FOREVER A HUNDRED YEARS monad... some... things... Me and monads runnin' around and...applicative functor time... a- all day long forever... All a - a hundred days applicatives and functors! Forever a hundred times.... OVER and over monad transformers... adventures dot com... W W W dot at lambda calculus and category theory dot com w..w..w... function composition adventures... Ah- hundred years… Every minute referential... transparency dot com.... w w w a hundred times... composition dot com...
Fig 1.1 What most people thing a typical functional programming advocate looks like
Regarded as eccentric crazies with wild ideas
Spout nonsense like "monads" every 2 seconds
Often bald
=<< Obligatory Quote >>=
Before I get to far in to it, I want to add some framing to the talk
My goal is not to teach you functional programming, my goal is to spark some curiosityt
=<< Obligatory Quote >>=
If you wish to build a ship, do not divide the men into teams and send them to the forest to cut wood. Instead, teach them to long for the vast and endless sea.
Before I get to far in to it, I want to add some framing to the talk
My goal is not to teach you functional programming, my goal is to spark some curiosityt
And I think this obligatory quote (every good talk has a quote) conveys the framework I used when writing these slides
Also we like boats and ships and stuff like that here, so make sense I guess.
=<< Obligatory Quote >>=
If you wish to build a ship, do not divide the men into teams and send them to the forest to cut wood. Instead, teach them to long for the vast and endless sea.
- Some French Guy. Idk. I'm not cultured. I'm Australian.
Before I get to far in to it, I want to add some framing to the talk
My goal is not to teach you functional programming, my goal is to spark some curiosityt
And I think this obligatory quote (every good talk has a quote) conveys the framework I used when writing these slides
Also we like boats and ships and stuff like that here, so make sense I guess.
And of course, don't forget attribution. So that everyone knows you're cultured and read important things
With that in mind, don't take any code examples too seriously, they are to demonstrate the big picture idea.
=<< What is this Talk About? >>=
So what is this talk about?
Let me start by telling you some things it is not about
Which is something you're not supposed to do as an educator but whatever
=<< What is this Talk About? >>=
This talk is not about:
Haskell
Convincing you to stop using whichever language you like
Mathematics
So what is it about?
When trying to explain to someone why they should learn functional programming, there are many perspectives to try explain it from.
For this discussion, I've settled on a very meta one. Perspective itself.
=<< What is this Talk About? >>=
Perspective
As said, this is not a talk about haskell, it's about viewing programming through different perspectives"
Please ask questions as we go!
Let's start the talk!
=<< What is Functional Programming? >>=
=<< What is Functional Programming? >>=
Programming with functions.
=<< What is Functional Programming? >>=
Programming with functions.
No, really. Everything is a function.
=<< What is a Function? >>=
=<< What is a Function? >>=
A mapping between sets that associates every element of the first set to exactly one element of the second set.
It's important to understand that that's it.
This is different to functions in procedural languages - actually the name "function" is a misnomer in that context. Really they should be called prodedures or subroutines (hence the name procedural)
A function is a mapping. It's equivalent to something like an array in PHP. It associates one value to another one
In the same way that a PHP array cannot mutate state, a function cannot
What I'm describing are actually pure functions, but for the rest of the talk I'll just be saying "functions"
This has some interesting consequences...
=<< What is a Function? >>=
No equivalent constructs for:
For loops
While loops
Gotos
Variables*
Probably a bunch of other constructs I forgot
*In pure functional programming, there are true variables. That is, once you declare the value of a variable, you cannot change it. Contrast this with procedural languages where you can reassign a variable whenever you like.
=<< Huh? >>=
And of course this all begs the question....
=<< Huh? >>=
Who in their right mind would wanna do that?!
You're trying to tell me FP is awesome be because it has ... less features?
This is true, but it makes no difference. You can accomplish anything in FP that you can accomplish in a procedural language
=<< Huh? >>=
Why tho?
Learning is good
Brain plasticity
Greater perspective
The best answer I can give is, "learning is good". I think that's something everyone at moodle can agree on
Learning FP is gonna require you to wrestle your brain in to shapes it's never taken before. Which will leave it with the plasticity to learn a greater variety of things you encounter.
It will also make the math/logic part of your brain very buff
As we know, the brain has 3 main cortexes. The passion cortex, the power cortext, and the logic cortex
As programmers we need to engorge mostly the logic cortext, but also the passion cortex - as this is a profession that involves other people.
Communicating about programs written in the functional style is actually easier than the programs written in the procedural style. More on that later
And lets not forget that our very own MoodleNet is written in Elixir. A functional language.
=<< Paradigms >>=
Paradigms
Let's talk about paradigms for a bit
In particular, let's talk about the two most widely used paradigms. Which also happen to be the most at odds
=<< Paradigms >>=
Declarative
Functional
Haskell
Elm
Elixir
Clojure
Imperative
Procedural
PHP
C
Java
DamoScript
So here they are. Declaritive and imperative, and inside those we see sub-paradigms (there are more, for example SQL is declaritive but not functional, and Assembly is imperative but not procedural - although the vast majority of imperative languages are indeed procedural):
And then inside the boxes we see some examples of language that embody that paradigm
For the purposes of this talk it's probably OK to just think of declaritive and functional as interchangeable, and some for imperative and procedural. I'll probably mix them up
So why am I showing this? Well, let's look at this through a different perspective... Some of you might have realised that imperative and declaritive are both words used to describe human language, and that's relevant
Learning a new paradigm is beneficial the same way learning a new human language is
=<< Gramatical Mood >>=
Declarative
A sentence which expresses a statement of fact.
He runs.
I like climbing.
Ice is cold.
Mathieu is shredded.
ImperativeA sentence which expresses instructions, or requests.
Shut the door.
Don't eat my burger.
Let's go to the pub.
Don't make eye contact with Craig.
We can see here that in the declaritive mood you express statements of fact. They aren't instrcutions
Contrast this with the imperative style of expression where there is a very clear instruction to carry out
=<< Gramatical Mood >>=
Declarative
This is this.
Imperative
Do this.
To make it more concise... here's the smallest definition I can think of
And this applies to programs too. In the functional paradigm we no longer have the "instruction words" - things like, for, while, goto, variable reassignment
=<< Big Brain Moment >>=
And that brings us to the first of hopefully many "Big Brain Moments"
=<< Big Brain Moment >>=
Programming languages ARE human languages.
We don't write programs for computers - we write programs for other humans.
=<< Why is declaritive mood good? >>=
But in both cases, it seems like we lose something useful in the declaritive mode. What do we get by giving up these things?
Surely giving instructions is useful, otherwise how do you do anything?!
=<< Why is declaritive mood good? >>=
Atemporality
=<< Why is declaritive mood good? >>=
Independant of or unaffected by time.
=<< Why is declaritive mood good? >>=
Declarative programs express what they actually do leaving more "brain space" to focus on solving the problem.
A declaritive program expresses its operation in terms of relationships.
In an imperative paradigm, thinking about the program means thinking about changes over time => keeping track of changes
In a declaritive one, thinking about the program means thinking about relationships => look at what the thing is, how it relates to the other thing, and move on
=<< To Recap >>=
Why tho?
Because sometimes there is such a thing as too much freedom
Functional programming is awesome because it stops you shooting yourself in the foot
"Constraints liberate, liberties constrain"
There are also classes of problems where the declaritive style is a more elegant way of expressing the solution
Some problems are simply very difficult to solve in an imperative way.
Especially when we are talking about events that are happening in parallel and may run at different speed/times
In the imperative paradigm, you quite easily come up against data races by virtue of the way the program is expressed
=<< Some Code (Finally) >>=
At this point I imagine a lot of you are thinking....
=<< Some Code (Finally) >>=
Enough of this philosophy and linguistics mumbo jumbo, already!
=<< Some Code (Finally) >>=
My favourite example
Consider:
x = x + 1;
and:
function repeat(x) {
return x + repeat(x);
}
OK, so what?
In the declaritive paradigm, this code hangs while this code runs. In the imperative paradigm this code hangs, while this code runs.
=<< Some Code (Finally) >>=
x = x + 1;
Declarative
"x is the same as itself plus one."
Complete nonsense!
Imperative
"Evaluate the thing on the right of `=` then store it in the thing on the left of `=`."
A list of instructions that can be followed.
=<< Some Code (Finally) >>=
function repeat(x) {
return x + repeat(x);
}
Declarative
"The repeat of `x` is `x` appended to the repeat of `x`"
An infinite list of `x`!
Imperative
"To evaluate the repeate of `x`, first evaluate the repeat of `x`"
...Yeah, you see the problem?
=<< Big Brain Moment >>=
Programming languages ARE human languages.
Let's take this time to reflect...
Imperative tells you what to do
Declaritive tells you what things are
=<< Some Code (Finally) >>=
Real Haskell code that runs
repeat x = x ++ repeat x
threeFs = take 3 (repeat "f")
> "fff"
Let's think about the way this is understood
threeFs is the first three elements in an infinite list of fs - totally fine, makes complete sense
Shame that the function name is "take" but whatever
=<< Some Code (Finally) >>=
Real JavaScript code that hangs
function repeat(x) {
return x + repeat(x);
}
threeFs = repeat("f").substr(0,3);
> InternalError: too much recursion
By contrast, this reads as "First compute an infinite list of fs" - which as we saw before was a problem. And even that human sentence clearly has a problem.
=<< Big Brain Moment >>=
What did declaritive mode give us?
Atemporality
The ability to wield infinity!
How cool is that? Because we can express what things are, we can express an infininte list!
None of the declaritive version of the program relies on us traking changes anywhere. We just need to know what a thing is and how it relates to another thing
=<< Promises >>=
Promises
Let's think about promises...
Seems like an odd tangent but let's go with it
And just as before, I'm gonna break one of the carinal rules of teaching by telling you what promises are not...
=<< Promises >>=
>:(
>:(
>:(
>:(
>:(
>:(
>:(
>:(
>:(
>:(
Promises do not make things asynchronous!
So there's a lot of misleading information out there about promises
Some people believe that promises "make" things asynchronous, but this isn't true
You can have perfectly synchronous promises, the thing you pass as a callbackto a promise does not get "run in the background" or anything like that
=<< Promises >>=
The real promises
What problems do promises solve?
Asynchronous request management
Error handling for computations which may fail
Probably more too
What are promises then?
A value (which may or may not be available yet) wrapped in some additional context
Functions to instantiate the wrapper (`Promise.resolve`, `Promise.reject`)
A rule for composing these wrapped values (`then`)
=<< Promises >>=
Terminology/syntax recap
JavaScript arrow functions
x => x + 1;
is equivalent to:
function(x) {
return x+1;
}
Composition
A method of combining two things of the same type in to another thing that is also of the same type
Shoutout Mat about arrow functions
A quick note on composition: So far you may have come across function composition. There's lots of different kinds of composition, but function composition is incredibly common, especially in programming. However in the example we are talking the composition of promises. In the sense that we combine to promises, and get another promise.
=<< Promises >>=
Promise composition
The `then` method of a promise accepts a function as an argument. This function takes a value and returns a new promise. The new promise "combines" the previous two using the "composition rule" given to `then`.
Promise.resolve("Some value").then(x => Promise.resolve(x + " and another value")).then(x => Promise.resolve(x + " and another one!"));
There are three promises in the above snippet. One, two, three.
Promise.resolve("Some value").then(x => Promise.reject("It's all gone wrong")).then(x => Promise.resolve(x + " and another one!"));
The above snippet still results in a promise, but it is a "failed" one. Any subsequent `then` after the `reject` has no effect.
Depending on how we go for time, I hope to discuss composition after this section.
=<< Promises >>=
OK great but who cares?
We are declaring how we want promises to compose
The order that the promises actually resolve their values in is not important
In other words, we don't have to worry about timing anymore
We can declare a failure anywhere in the chain
=<< Promises >>=
atemporality?
declaritive?
functions?
composition?
This sure is starting to sound familiar.
=<< Promises >>=
Woah!
JavaScript
Promise.resolve("We start here")
.then(x =>Promise.resolve(x + " then get here"))
.then(x =>Promise.resolve(x + " and finally here!"))
Haskell
Right("We start here")
>>= (\x -> Right (x ++ " then get here"))
>>= (\x ->Right (x ++ " and finally here!"))
It does not matter what order the promises resolve in, the final promise will always be resolved with "We start here..."
In this specific example, there is nothing asynchronous happening, but it's not much work to adapt it so there is. I just wanted to really highlight the similarities with haskell
=<< Promises >>=
Woah!
JavaScript
Promise.resolve("We start here")
.then(x =>Promise.resolve(x + " then get here"))
.then(x =>Promise.reject("Oh noes!"))
.then(x =>Promise.resolve(x + " and finally here!"))
Haskell
Right("We start here")
>>= (\x -> Right (x ++ " then get here"))
>>= (\x ->Left ("Oh noes!"))
>>= (\x ->Right (x ++ " and finally here!"))
Likewise, we can put a failure anywhere in the chain. It doesn't matter if the failure happens first, last, or anywhere in between. The result is always a failed promise of "Oh noes!"
So, if you've ever used promises, you've been doing declaritive style programming without even realising it!
They give us some new powers, we can now write atemporal code, which explains why they emerged in JS, a place where people are constantly dealing with requests that can finish in any order
So it's super cool that people using a language very far removed from haskell ended up solving the problem in the same way
Although both are independed discoveries, I don't think it's a coincidence promises appeared given the nature of the JS world.
=<< Composition >>=
Composition
Let's think about composition...
Mat touched on function composition briefly in his talk
I wantto talk about it in a more abstract sence. I think the idea of composition is so important that it deserves its own little bit
=<< Composition >>=
=<< Composition >>=
If we can go from here to here
=<< Composition >>=
If we can go from here to here
And we can go from here to here
=<< Composition >>=
If we can go from here to here
And we can go from here to here
Then the composition (if it exists) goes from here to here
RETURN LATER: Come back to this slide after looking at the next one
We want to go from A to C - but maybe that's really hard
Perhaps someone worked out how to go from A to B, and someone else worked out how to go from B to C
Well, if we're in a system where composition is possible, then we just solved the problem!
This is the natural way people solve problems
RETURN EVEN LATER: After returning from the end slide: explain how side effects break composition
Maybe A->B has a side effect, this means when we call B->C with the result from A->B, it may not be the same as calling A->C. The point of composition is that the outcome should be the same.
Don't talk about it unless needed: Referential transparency. f(a, b) => return print(a + b) + print(a + b); is not the same program as f(a,b) => c = print(a + b); return c + c;
Procedures in imperative languages are a short sighted attempt at composition
In the functional paradigm, composition is gauranteed because functions cannot have side effects
=<< Composition >>=
OK great but who cares?
Go back to the full composition diagram
=<< Composition >>=
OK great but who cares?
Big problems can often be chopped up in to smaller, easier to solve problems. If we can be clever about how we chop them up, such that the solutions to the individual problems can compose together to form a full solution, then we can infinitely speed up the process by adding more workers!
=<< Composition >>=
Examples
The pyramids
The LHC
McDonald's
Moodle!
The pyramids were build by having loads of peope work in parallel
Same with the LHC. I don't believe there is a single person in the world who fully understands it
Instead of having one chef "make a burger" - staff make individual parts of the burger and compose it together - I think McDonald's was the first place to do this
And Moodle does it too! Let's think about how we tackle projects...
=<< Composition >>=
So... do we get one mega awesome dev to bash out features?
=<< Composition >>=
"With these biceps I can solve ANYTHING"
idk about you, but I wouldn't be keen to work with this person
There's a thing in dev called the 10x developer, and it is something that simply does not exist
The correct way to work on software is of course...
=<< Composition >>=
No, you get friends to take a piece and help!
henlo
henlo
henlo
henlo
henlo
henlo
As a team!
This is why it's worth spending the time to plan things and figure out how to "chop up" the work
We need to make sure we are chopping the problem up in to pieces that can be composed together later
=<< Composition >>=
Composition is nature's greatest hack
My goal here was to try and convince you that composition really is important and is fundamental to the way we think
Humans are amazing for our ability to break down problems in to manageable chunks and then compose them together.
At its core, composition is about relationships, and building complexity by combining them. Hey, wasn't the whole declaritive thing about relationships?
And that brings me to my final point
=<< Composition >>=
What's this got to do with FP?
When writing programs (as an individual in this case, not as a group) we naturally want to break the solution up in to "building blocks" that we put together to solve the problem (it's composition again).
The building blocks you use matter. Some compose better than others. Because of all the restrictions the functional paradigm places on the programmer (lack of mutation, lack of control flow), functions in a pure language are naturally well-suited to composition.
This is becoming more relevant than ever in the age of parallel computing
Go back to the composition slide and explain that in FP the composition is gauranteed to exist, while in other paradigms it is not
=<< Closing Notes >>=
I'd like to finish this talk with some food for thought...
=<< Closing Notes >>=
Applications to life:
We work across multiple timezones, so being able to solve problems in a time-independant way seems appealing, doesn't it?
Moore's law is coming to an end, now the focus is shifting to parallel computing
Imperative paradigms will not be the right tool for this
Either we'll see a shift to declaritive style programming
Or we'll make life hard for ourselves real fast
Maybe quantum mechanics is so damn confusing because at a certain point we can't decompose things anymore?
After all... why should the universe conform to the way our brains want it to be...
In regards to Moore's law, I personally hope we start seeing a paradigm shift soon. Because that's the definition of madness really. Doing the same thing over and over but expecting different results.
Other analogies like the frog in slowly boiling water come to mind