We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

What Every Hipster Should Know About Functional Programming

00:00

Formal Metadata

Title
What Every Hipster Should Know About Functional Programming
Title of Series
Number of Parts
150
Author
License
CC Attribution - NonCommercial - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Identifiers
Publisher
Release Date
Language

Content Metadata

Subject Area
Genre
Abstract
Different programming paradigms serve different purposes. Systems programmers prefer tools that are dumb, imperative and close to the metal. Enterprise programmers prefer tools which foster complexity, increasing billable hours and the client's dependency on the developer. And, let me just come clean and admit it, functional programmers do it for that delicious feeling of superiority that comes from looking down your nose at the normals in their caves banging together for loops and mutable state to make fire. Treat yourself to a crash course in the vocabulary of functional programming: lambdas, higher order functions, purity and immutability, the infinite opportunities to throw the word "monad" in the face of anyone who thinks an ironic moustache is enough to justify all that self-assured smugness these days. You'll never have to lose a programming argument again once you've learned where to casually toss terms like "applicative functor" and "Kleisli triple" into the conversation. This is the War of the Hipsters. Arm yourself now, before it goes mainstream.
Regulärer Ausdruck <Textverarbeitung>Level (video gaming)Message passingInsertion lossRevision controlPhysical systemMultiplication signMusical ensembleHost Identity ProtocolRight angleSocial classFunctional programmingRegulärer Ausdruck <Textverarbeitung>Letterpress printingSystem programmingVirtual machineClosed setLengthSoftware developerForm (programming)Imperative programmingComputer programmingWordProgramming paradigmObject (grammar)Video gameRow (database)CASE <Informatik>MereologyMachine codeBitWeb-DesignerProgrammer (hardware)Regular graphComputer virusGoodness of fitComputer animation
Programmer (hardware)LogicWordSpeciesLogic programmingMetropolitan area networkFunctional programmingInsertion lossRight angleComputer programmingSoftware developerComputer animation
Software developerJava appletProgrammer (hardware)Functional programmingCategory of beingFormal languageBranch (computer science)Object (grammar)AdditionComputer programmingCausalityEndliche ModelltheorieMathematicsPressureSystem callRule of inferenceTheorySmith chartComputer animation
TheoryCategory of beingFunctional programmingTunisGroup actionPoint (geometry)MathematicsProgramming languageBitMathematicianInterpreter (computing)NumberFormal languageStudent's t-testAbstractionString (computer science)Revision controlType theoryMachine codeHecke operatorData typePositional notationCalculusComputer iconMcCarthy, JohnVideo gameVirtual machineRight angleSocial classComputer animation
Function (mathematics)String (computer science)Computer virusFunktorPiWeightFunctional programmingFormal languageSocial classObject (grammar)Parameter (computer programming)Lambda calculusMetropolitan area networkDifferent (Kate Ryan album)Type theoryProper mapElectronic mailing listBit rateCASE <Informatik>Variable (mathematics)Physical systemFilm editingWhiteboardString (computer science)Multiplication signSpherical capVideo gameLevel (video gaming)Rational numberCategory of beingTerm (mathematics)Service (economics)Right angleTheoryState of matterResultantCombinational logicAutomatic differentiationElement (mathematics)Power (physics)ImplementationExpressionPlanningJava appletArtificial lifeRule of inferenceIterationFunktorBitAliasingLoop (music)Computer animation
PiFunction (mathematics)String (computer science)Reduction of orderDigital filterIntrusion detection systemComputer-assisted translationSinc functionReduction of orderCASE <Informatik>Electronic mailing listPosition operatorResultantFunctional programmingString (computer science)IterationParameter (computer programming)MereologyImplementationInitial value problemPoint (geometry)SummierbarkeitMappingFactory (trading post)Element (mathematics)Total S.A.Software testingLevel (video gaming)Java appletCategory of beingData structureRevision controlWordIdeal (ethics)TheoryVariable (mathematics)BitSpherical capOperator (mathematics)Latent heatAdditionBoilerplate (text)Matching (graph theory)Office suiteSystem callDependent and independent variablesRational numberShared memoryFrame problemOcean currentInheritance (object-oriented programming)MassForm (programming)SpacetimeAutomatic differentiationFreewareOrder (biology)Graphics tabletRight angleBit rateFormal languageCodecComputer animation
String (computer science)Function (mathematics)PiHand fanData typeCategory of beingElectronic mailing listSpherical capFunctional programmingSurjective functionCombinational logicNumberSquare numberResultantData storage deviceGeneric programmingReduction of orderInheritance (object-oriented programming)Exception handlingCASE <Informatik>Pointer (computer programming)LogicAbsolute valueBranch (computer science)Combinatory logicBitData structureDatabaseLevel (video gaming)Parameter (computer programming)Factory (trading post)Expected valueType theorySpacetimeCellular automatonFreewareMultiplication signAreaPosition operatorComputer clusterMereologyPoint (geometry)WordTerm (mathematics)Computer animation
Function (mathematics)String (computer science)Computer virusFunktorElectronic mailing listComputer multitaskingCAN busUltraviolet photoelectron spectroscopyPiAeroelasticitySpherical capCellular automatonPlanningFunctional programmingDemosceneSystem identificationElectronic mailing listChainOpen setMetropolitan area networkInheritance (object-oriented programming)Parameter (computer programming)Error messageCombinational logicFormal languageRight angleAdditionCASE <Informatik>CausalityBuildingComputer programmingoutputBlock (periodic table)Type theoryMathematicsDependent and independent variablesElectronic visual displayReading (process)State of matterSequenceResultantObservational studyFreewareString (computer science)NP-hardMultiplication signCommutatorCartesian coordinate systemLevel (video gaming)CodeData typeNeuroinformatikFunktorJava appletGoodness of fitOnline helpWordComputer animation
Function (mathematics)ChainParameter (computer programming)SequenceArc (geometry)Reduction of orderMonad (category theory)Parameter (computer programming)Functional programmingMonad (category theory)TheoryNumberFlow separationNeuroinformatikWordResultantGoodness of fitPhysical lawWell-formed formulaCartesian coordinate systemPartial derivativeMetropolitan area networkCASE <Informatik>Context awarenessDivisorSurjective functionState of matterFormal languageIntegrated development environmentMathematicsTelecommunicationSign (mathematics)Category of beingExpected valueAdditionSequenceChainGeneric programmingTouchscreenSpacetimePoint (geometry)Letterpress printingReading (process)ImplementationInfinityLine (geometry)Right angleComputer scienceAutomatic differentiationAreaLevel (video gaming)Insertion lossComputer animation
Monad (category theory)Order (biology)ExistencePhysical lawAeroelasticityFunction (mathematics)Element (mathematics)Instance (computer science)Category of beingLengthRecursionTransformation (genetics)FunktorMereologyMonad (category theory)Element (mathematics)Execution unitElectronic mailing listCASE <Informatik>Slide ruleFamilyParameter (computer programming)Functional programmingCrash (computing)System callForm (programming)Bookmark (World Wide Web)IsomorphieklasseLogic programmingStandard deviationSoftware developerLibrary (computing)Keyboard shortcutPoint (geometry)AdditionElectronic signatureCodeBitVariable (mathematics)outputPhysical lawResultantCorrespondence (mathematics)Arithmetic meanProper mapMultiplication sign2 (number)Data structureNetwork topologyMassTrailMetropolitan area networkBoolean algebraAssembly languageRight angleSign (mathematics)WordRückkehrpunktOffice suiteValue-added networkCategory of beingSoftwareMoment (mathematics)Workstation <Musikinstrument>IterationData storage device8 (number)Complex (psychology)PlanningData miningCore dumpComputer clusterLevel (video gaming)Computer animation
Link (knot theory)Line (geometry)Right angleGreatest elementWeb browserSlide ruleCodeJava appletProgrammer (hardware)NeuroinformatikUsabilityMultiplication signFormal languageGoodness of fitMonad (category theory)Metropolitan area networkAnalytic continuationDescriptive statisticsPoint (geometry)RecursionPlastikkarteFunctional programmingForm (programming)MassTheoryCASE <Informatik>Category of beingBitProgrammschleifeLoop (music)ExpressionBranch (computer science)Computer clusterEndliche ModelltheorieCombinational logicProcess (computing)Software maintenanceNumbering schemeMathematical optimizationComputer programmingTowerComputer animation
Transcript: English(auto-generated)
So, hello. Good morning. Kapla, if I may just speak Klingon. Yeah, so hello, my name is Bunil and I am a web developer. I work at a company called Komoyo, which is like Telenor's version of Xerox PARC.
I should mention we do a lot of cool stuff. We are hiring. Just saying. That's going to be my only commercial message today, because I want to talk about hipsters. Do you all know what hipsters are, right? Hipsters like better music than you. They dress cooler than you. They generally
are a lot better than you, at least according to themselves. And of course translating that to our business, hipsters tend to be functional programmers. And there's a reason for that.
Functional programming to the uninitiated sounds awfully complicated. It has all these strange words that you don't understand, that quite possibly the functional programming hipsters don't understand, but they know how to say the words so they can make you guys feel stupid, right?
I'm sure you've been on the receiving end of that a couple of times. So, my aim for this talk is to teach you guys those words and give you a bit of an idea of what they mean in the simplest sense,
so that you guys can go back to your co-workers and use those words on them and make them feel stupid and make you guys look smart. So, oh, wait. I actually got a costume for this talk,
because hipsters come with ironic glasses. The thing is, though, this isn't the first time I've done this talk, and finally some recordings of previous versions have been released. So I've actually noticed that when I wear these glasses, I look like a grandmother. So the last thing a hipster wants to do is something old,
especially looking old, so I'm going to skip those. If you don't mind. I did look horrible, right? Yeah, I did. I can tell. Right, well, let's get started. So, first of all, I would like to introduce you to
what I have identified as the four great paradigms of programming. First of all, there is the original systems programmer, the imperative programmer, the C programmer, staying close to the metal. Preferably, you know, even writing machine code.
These guys, yeah, one of those guys actually invented regular expressions, in case you don't recognize them. That's Ken Thompson and Dennis Ritchie, who invented C. These guys looked the part on systems programmer, as well, as they should, because you all know that the length of the bed is proportionate to the skill level of your C programming.
Also, check out the cool hipster glasses on Dennis there. Then there's the object oriented programmer. That's you guys, most likely. Picture here in the natural habitat.
I'm sure you've been there. I certainly have. And yeah, that looks kind of stupid. That's the idea. So, that's the functional programmer. The functional programmer is smarter than you. The functional programmer knows lots of fancy words and has fake glasses, as well.
And finally, that's the logic programmer. And the logic programmer, well, logic programming in general is perhaps something that mankind as a species isn't quite evolved to be able to deal with yet.
So, let's just leave that for the next century or something. But to cut a long story short, there are two kinds of developers you want to be concerned with. There's the functional programmer. Wow. The functional programmer, who, in addition to having an amazing moustache, of course,
is smarter than you. And there's you, the muggle. I can tell I'm in a room full of object oriented programmers. You guys relate to this, right?
Actually, this is a Java JEGS. You see Java guys that are probably a lot smarter. So, yeah. Now, functional programming mostly, the language of functional programming tends to have leaked into the general consciousness from a language called Haskell.
Haskell was designed by a committee of academics for the pleasure of other academics. In fact, one of the guilty parties is sitting right up front here. I'm not going to call him out, but thank you for Haskell. And the reason Haskell has this wonderful language of confusion
is that Haskell derives most of his ideas from something called category theory, a branch of mathematics, that... Yeah. It's actually not that kind of category.
It's best not gone into in detail. Let's just remember category theory. And so functional programming in general. I figured I'd give you an idea of how that came about because it's quite an interesting story.
So, the first programming languages were designed to be kind of a slight abstraction of a machine code. On the other hand, there was this guy called Alonzo Church. He was a mathematician. And he invented something called the Lambda Calculus.
There was this other guy called Haskell Curry. Remember that name. It's going to recur a bit throughout this presentation. And he kind of got involved in the design of the Lambda Calculus as well. The idea is that
the Lambda Calculus is composed only of functions. We don't mess with concrete, messy things like values and numbers. The Lambda Calculus is just functions. A function can return another function or it cannot. It doesn't bother with strings and data types and horrid things like that.
Let's just go with a funny picture. The Lambda Calculus eventually evolved into something called the type Lambda Calculus, the simple type Lambda Calculus,
which perhaps looks a bit more useful to us human beings. Which, of course, Haskell Curry violently disapproved of because he's a mathematician, not a human being. It turned into something slightly more useful, as I said.
Incidentally, there was this guy called John McCarthy, who, just as an experiment, took the Lambda Calculus, made his own version of it, his own notation for it. One of his students decided to, hey, let's try and write an interpreter for this version of the Lambda Calculus,
just for the heck of it. It turned out that that actually worked. He had designed, without really meaning to, a language based on pure mathematics, a programming language based on pure mathematics. That was in 1958 and the language was called LISP.
That was the very first functional programming language. But what does that mean, functional programming? Well, it is essentially based on the concept of first class functions. As I mentioned, the Lambda Calculus has functions that only return other functions.
Functions are values. Functions can be passed in as arguments to other functions. They can be returned from other functions. They can be stored in variables, much like what you might be used to from object oriented languages.
Except C Sharp, of course, has caught up and added the idea of first class functions after a while. Java is still trying to catch up. They're getting them, but it certainly took them a while. So let's have a look at first class functions. Let's do some live coding. Now, of course, I should inform you of the rules of live coding.
Since I'm not Venkat Subramaniam and Han's not perfect, there is a chance that I'm going to make mistakes. You need to spot those mistakes. This is on you. If I screw up, that's your fault. Great. So this is JavaScript. Or in fact, it's not quite JavaScript. Notice this type annotation on the function.
This is in fact TypeScript, Microsoft's JavaScript with a type system. I'm going to go through some examples that get progressively more complicated. I figured the type annotations might help you just follow along. So this means that we define a function called hello,
which takes no arguments, and it should return a string. As you can see, it does. So calling this, we see that it returns the string, hello everypony. This should be no surprise to you,
but this is actually how I originally discovered function programming a bit by accident. Instead of calling the function, I just did away with the parentheses, and suddenly, wow, the function is actually a value. So what can we do with that?
Say we could perhaps take that value, assign it to another variable. Can we call that? Yeah, we can. We just pass it on. And how about this? This is a stretch, right? This can't possibly work. We define a function which takes an argument f,
specifying that it should be a function, and then just call f. And then if we go call this, hello. Doesn't that work? Sorry.
Of course. I'm too used to proper function languages where the return is implied. That's my excuse, right? See, that works. We actually just took a function and passed it into another function, and the other function could just call that, like, alias. So that's first class functions for you.
You can pass them around any way you like. They're values, just like numbers and strings. That's pretty cool. That lends itself to certain use cases that are quite common in function languages. This is very common. I'm sure you've seen this in your own languages,
but we're just going to implement this from the start. And this is why category theory is starting to shine through, because a functor is a funny word, right? You haven't heard that word before, probably. In some languages, a functor simply means a function. I believe Prolog does that.
But a functor in category theory is explicitly defined. Though this is my definition, so that's probably a mistake, but never mind. A functor is a collection of f that can apply a function f from x to y over itself to create a collection of y. That should be quite clear to everybody, right?
The idea of a functor is that you have a collection type. Let's just go with lists from now on, because lists are easy to understand. Or arrays in JavaScript, they're the same thing. It's just a collection of values. Indexed collection, perhaps. So suppose you have a function that takes a value of the type that the list contains.
And it returns something else. So given that the list supports functors, the idea of functors, we have a map function that takes your function that operates on single values,
and it applies that to the list so that we magically transform it, like running the function on each value. I'm just going to show you that, because it's very easy to see. Suppose we have a function caps. It takes a string, returns a string, and turns it to uppercase. We have a list of ponies, and we're going to implement this map function.
It's quite easy. We get a function n. It's specified that the function takes one argument of any value, returns another argument. No, it returns a value of any type.
And it takes a list of any type. And it finally returns a list of any type. So we need to construct a new list. We're just going to do a stupid for loop to implement this. So essentially what we do is for each step through the iteration,
we push onto the new list the result of calling func on the ith element of list. Now I'm going to actually remember to return this.
So just a follow-up, iterating through the list, applying the function for each iteration. So we have ponies. Do you like ponies? Who likes ponies? I know you do. There are actually people willing to admit it. That's very brave of me. Usually I ask, I can ask the audience if there are any ponies,
and everybody just goes, no, not me. I like cars and power tools, but... Very brave of you. So we have a list of ponies. Rainbow Dash, Pinkie Pie, and Twilight Sparkle. Let's try using that map function on our ponies.
So we first specify the function that we want to apply. And then we specify the list of ponies. Now what's going to happen when I evaluate this? Rhetorical question, right? It's going to go uppercase, yeah. So you see that the caps function works on only one pony at a time.
And we just apply that to the whole list. That is a functor. Well, the functor is the combination of the idea of the collection and the map function. So nothing's ever easy in category theory. But what we're doing here is essentially a functor. So I mentioned that you've probably seen this before.
In fact, JavaScript comes with this map function defined on the array object. So we could have just gone ponies.map, caps, and this is JavaScript's native implementation. It does the same thing, as you can see. Most people call this mapping. If you heard of MapReduce, this is the idea of the map there.
Of course, you guys are going to be functional programmers, so you call this functors. At least now you can. I'm just going to go through another common, very similar use case, a filter function. The idea is that we have a function that, instead of returning a new value, returns a boolean, quite simply.
So this is a test. It tests if a pony is too cool. Of course, Rainbow Dash is too cool for most things, so it returns true if the pony is not Rainbow Dash. The too cool test is intended to filter out ponies that are too cool.
Hence, for Rainbow Dash, it should return false. Let's implement that filter function. We have the same structure as the map, except that instead of just applying a function, we call that function on the ith element of list, if that is true.
Sub-languages like to be explicit about this, right? In JavaScript, everything is truthy, almost, so we're not going to bother. If this is true, push the unchanged value onto the new list, and then we return that.
Meaning that if we apply the too cool filter on ponies, we should have a list without the coolest pony. Because Rainbow Dash doesn't want to be in a list with, you know, earth ponies and unicorn ponies, right?
I suppose, just as an experiment, we flip this. So, in an absurd, imagined world, where Rainbow Dash is the only pony who isn't too cool to be in this list, we see that the list now only contains Rainbow Dash instead.
So we're essentially just filtering on the truthiness of that function. Now, reduction. Reduction. That is the other part of MapReduce. The idea is that you have a function which takes two arguments,
and of course returns one value. And the idea is that we, for each element of the list, we take the accumulated value of going through our iterations. That is A in this case, and the point in the iteration is B.
And we just run that function through that, and it kind of accumulates the result. This is hard to explain, so I'm just going to implement it. Once again, new list. Or in fact, let's call it result, because it's not necessarily a list.
And notice that in addition to the function and the list, we take an initial value. So we're going to start with that initial value. You should have pointed out that typo. I'm watching you. And we need an iterator variable.
Now, what we do is for each step through this iteration, we call func on the current result and the current value. The value of the current position of the list. And we just put the result of that back into result.
And then we return result. So, what can we use this for? For one thing, since I have an add function prepared, I think you can probably guess that. That's probably useful somehow. Let's suppose we have a list of one, two, three, four, and five numbers.
And let's start with an initial value of zero. Care to guess what that does? Sum of the numbers. It essentially just starts out with zero, goes to zero plus one is one, one plus two is...
Three plus three is six and so on until you get the total. So that is a reduction. Interestingly, reductions are also known as catamorphisms.
This is category theory for you. We didn't go with simple words like reduce. To be precise, a catamorphism is a right reduction. So we should have been iterating from the end of the list to the front if this were an actual catamorphism. But close enough. At least now you can use the word catamorphism and that's what matters, right?
So, reduction has an interesting property. Because it turns out that the map operation is in fact just a special case of a reduction. We can do map with just reduce.
Let me show you how. Suppose we have a function called shout2MapReducer. That takes a list of strings as its first argument and just a string as its second argument and it returns a list of strings.
Now this simply concatenates onto the list A, a list containing the uppercased version of B. Nothing more fancy than that.
Let's reduce that. shout2MapReducer on ponies and the empty list. Looks familiar. I just essentially mapped the caps function over that with a bit of boilerplate.
Now, we've got something called higher-order functions. Higher-order functions, that means essentially that functions can take other functions as arguments as we've seen. It also means, more interestingly, that functions can return other functions. In essence, you can write functions that are function factories, or function factory factories if you're more familiar with Java.
The ideal higher-order functions is that you can use functions to modify other functions or create functions for specific purposes.
I'm going to show you. In fact, we could generalize the case of the shout2MapReducer. Suppose, once again, we have the caps function, here's shout2MapReducer. Just check that that still works. onPonies and the empty list. That works.
Now, suppose that we want to generalize the way that we turn a function suitable for mapping into a function suitable for reducing. Let's just write a generic MapReducer, or MapReduceFactory. No, let's just go with MapReducer.
It takes a function with one argument that can be anything, and it returns anything. What it actually returns is a function that takes two arguments, as you will recall, the function you passed into reduce should.
Function! Very good, you're learning. I like that. That function essentially does the same thing as the shout2MapReducer.
It concatenates the results of calling func onP onto a. Let's just get rid of this reduce. We should be able to say reduceMapReducer of caps onPonies and the empty list.
So that should take the caps function that only takes one argument into something that takes two arguments and emulates map through a reduction.
And it does. Yay, that's a high-order function, and you know what they are. So, combinators are essentially high-order functions as well, but the idea of combinators is that they modify a function in a fixed way. So it's less of a factory function than kind of an operator, perhaps, on functions.
You might have heard of combinators already, things like the Y combinator, which is a combinator for getting you funded. And there are other combinators, like the S combinator and the B combinator, and there's a whole branch of logic devoted to combinators.
Let me just show you the stupidest example possible. So I have a function square. It can take a numeric argument and it returns the square of that argument. I'm going to invent a combinator for you. I'm going to call it the 3 combinator.
So, the 3 combinator works on a function, so we need an argument for that. It's a function that takes one numeric argument and returns a numeric value.
And it returns a function that takes a number and returns the resulting calling function on that number plus 3. So, applying the 3 combinator to our square function, that gives us a new function as expected.
Let's store that. Square and 3. Now, what does this do?
28. So the 3 combinator essentially just takes any function that operates on one number and adds 3. That's super useful, right? You can see the pointer combinators are ready, I'm sure. Actually, let's see something a bit more useful.
Absolutely. The 3 combinator only needs the return value to be a number.
That's correct. So, I thought I'd introduce another combinator called the null combinator. That should be a little more useful. Suppose we have a function, PonyType, and we have a data structure representing a pony.
Pinkiepie and she has a type, everypony has a type. Pinkiepie is a Pegasus pony. Suppose we call PonyType on Pinkie. That returns Pegasus pony. Does that look right? I thought you guys said you were bronies.
At least it should be somebody. Pinkiepie is an earth pony. You stupid, ignorant people. Right, now it looks better. Great, so suppose we just fetch Pinkiepie out of a database. And that seemed to work. Now, let's suppose we try and fetch Rainbow Dash out of a database.
Rainbow Dash is obviously way too cool to be fetched out of any old database. So, let's suppose that the result of the database query is null because it failed. What happens if we go PonyType on Rainbow Dash? Exception.
That's an error. That's not good. So, the null combinator is the idea of wrapping a function in an automatic null check. We have a function. It takes one argument, any type, and returns anything.
And it returns a function that takes an argument X. If X is null, return null. Else, return func OX.
So, null save PonyType is null check applied to PonyType. Let's just check that it still works for the expected case.
It does. It still fails here because we're not using it. Now, instead of crashing your program, it returns null when null comes in. Of course, you should do better than that in your own code. There's something called error handling, right?
You should at least display an error message instead of just swallowing it silently. But as I know you guys tend to do that anyway, at least now I've made it more comfortable for you. You can thank me later. Okay, that was combinators. Now, let's look at composition.
This is where functional programming, to me, starts to get really useful. Because composition is the idea, essentially, of reuse in functional programming. As opposed to inheritance in Java and C Sharp and things like that. The idea of composition is quite simple. Suppose we have two functions. One, the function caps, which we know.
And a function, hi, which simply says hi using my having input. So, let's make a composed function. It takes one function. It takes one argument. And another function that takes one argument.
And types don't matter in this case. We return a function that also takes one argument. And returns the results of calling function two on the results... Wait, there we are.
I don't know what happened there. Calling function two on the results of calling function one... Oh, I see what I did. Why didn't you guys tell me that? Undo, undo. Oh, there we are. Func one, X.
The idea is that we take two functions and string them together. Returning a function that is a chain of those two functions. Suppose we call caps on hi on everypony.
So we shout, hello everypony. Composition is the idea of composing those two functions together. Hi and then caps. That gives us a function that we can just call with everypony. And it does the same thing.
Now, this might not seem immediately useful to you, because it's a contrived example. However, most function languages come with basic functions that you can use as building blocks to kind of compose computation chains using the idea of composition.
So it's actually very, very powerful. And it isn't just involving saying hi to other ponies. But you can do that too. Applicative functions. I only really included this, because it's a great word. Applicative functions.
Starting to sound very, very complicated, right? The idea of an applicative function. This is my naive implementation of the special case of an applicative function on lists in JavaScript. Don't look at it. It looks horrible. I'm just going to show you how it works. The applicative function is a function which also has,
in addition to the map function, an applicative map function. And the applicative map function lets you specify more functions and more lists, not just the one that the map gets. So suppose... Do we have hi and caps? I think we do.
Suppose we go hi and caps on ponies. Notice that instead of... What am I doing? How come you didn't spot that? You're sleeping. So instead of specifying one function, I specify a list of functions
and ponies as arguments. So what happens is that it tries to do every possible combination of the inputs. So we see that first it does hi on every pony in the list, and then it does caps on every pony in the list. Yay. Now let's do something a bit cuter.
Suppose we have a function hug. It takes one pony and another pony. And what do you think they do? Hugs. Right. So input two ponies and they hug each other.
Of course, then we're going to need more ponies. More ponies. So, help me out, guys. I'm looking for the main six. We have three already, right? Rainbow Dash, Pinkie Pie, Twilight Sparkle,
Applejack. Very good. Awesome. Okay, two more. No? Rarity. And?
This pony is really popular. You should know this. My little? No. But that's the general case. Fluttershy. All right, now we have two lists of three ponies. Let's use the applicative map function to make them hug each other.
So I just passed the one hug function. I still need to pass it in a list. But in addition to ponies, I pass in other arguments, more ponies. Because hug expects two arguments, so I need to pass in two lists. Now what happens? Every pony in the first list
hugs every pony in the other list. Every possible combination of that. That is how the applicative map function works on lists. It's not very useful, but it's very cute. Applicative functors are a lot more useful given other data types than lists.
Just take my word for that. If you're interested, then read a book and ask a little scholar, whatever. But at least, ponies hugging each other. Right? Okay. Corrine. Of course, this is the most overused illustration for corrine ever.
So I'm using it ironically. Corrine is the act of transforming a function of several arguments into a chain of functions of one argument that will yield the same result when called in sequence with the same arguments.
I think actually the formula below that is a lot clearer than the text. The idea is that, suppose you have a function that takes three arguments. Corrine is the act of turning that into a function that takes one argument and returns a function that takes the next argument, that returns a function that takes the next argument, that returns the results.
And the result is the same as calling the initial function with all three arguments. Corrine, as you might have guessed, was named for Haskell Corrine, who invented the idea of corrine. Okay. Just that it turns out that a couple of years earlier,
some guy called Moses Schonfinkel actually invented them, but word of it didn't reach Corrine's ears until later, much later, if Corrine even knew, I suppose he must have. The thing is Schonfinkel, I believe he was living in Stalin's Russia at the time, and apparently communication between Stalin's Russia and the rest of the world
wasn't doing that great. I don't know if he was in a gulag or something like that, but it sounds exciting, so let's imagine he was. So if you come across somebody actually knowing about Corrine and talking about Corrine and kind of upstaging you
because then you wouldn't look quite as smart using the word Corrine, just point out that's Schonfinkeling. Okay. Now let's look at Corrine. I already erased an implementation for you. It gets strange because JavaScript is a strange language.
The thing is, for one thing, in JavaScript, you have no way of telling how many arguments a given function expects. So my generic Corrine function takes the function and also needs to know the arity of the function. That's a nice one. Not a pony, that's rarity.
The arity of a function simply means how many arguments it takes. So a function of arity three takes three arguments, quite simply. I've written an add function that takes any number of arguments, which lets me Corrine that.
Suppose we want one that takes three arguments. So let's just check that this add function works. One, two, three. Six. Looks good. Let's Corrine that.
Okay. That returns a function. It takes one argument, one. That returns another function, which takes one argument, two. That returns another function, which takes an argument, three, which returns the result of the computation.
So that was a Corrine function for you. It doesn't seem immediately useful either, does it? Actually, there's a special case of Corrine called partial application. That's probably what you're going to come across most often.
And that is starting to become useful because it lets you encapsulate some kind of state into a simple function by prefilling arguments. Let me show you. Suppose we make a variable one and two and,
which is the partial application of and with arguments one and two. So that gets us a function, which we can then call with one argument
and get one and two and three, right? Six. Or more than one argument because and takes any number of arguments. So four in addition gives us ten. That looks right, yes. Fifteen. So partial application is a way of kind of prefilling arguments to a function.
If you think about it, that lets you actually store some kind of context or state even in the function that your partial application factor is creating. Trust me, that is super useful. But this is why partial application is interesting
because most people actually confuse Corrine as a whole with partial application. Which means that if you catch somebody talking about partial application and calling it Corrine, you can call them out on that and make them look stupid. You can buy them in bears later, if you like, for that.
Okay. Now the big one. You ready for this? Monads. Monads were of course invented by the German philosopher Gottfried Wilhelm von Leibniz. And those monads have nothing to do with monads in category theory.
They just happen to have the same name. Also, Leibniz looks awesome in hipster glasses, so I had to put him in. In a more practical sense, monads in category theory were introduced into computer science. With Haskell, of course. By a man named Philip Woodler. In fact, the only guy I didn't have to photoshop a fancy costume onto.
And monads were introduced into Haskell because Haskell is a purely functional language. Which means that functions in Haskell can have no sign effects.
They cannot change the environment around it. They can't even print hello world because that would be a sign effect. So, monads were introduced as some kind of magic to cheat and get around the fact that Haskell is a totally pure language.
And would be completely useless if you couldn't even print hello world to the screen, right? So, Philip Woodler discovered that you can actually cheat and do that in a purely functional language by using monads. The ideal monad specifically in this case. And monads are defined by the three monad laws.
These are not the three monad laws. The first monad law is you do not talk about monads. The second monad law is you do not... Yeah, you get the idea. There's actually some truth to that. Because it is traditional.
Because monads are so hard to understand. And those of us who do understand them like to remain an elite. So, it is traditional that once you understand monads you are supposed to write an extremely confusing tutorial on monads. Put it online and make sure that nobody else understands it.
This has been done thousands of times already. Right, but the best part about monads is that monads are also known as clicely triples. Doesn't that sound awesome? Clicely triples. I love that one. It is just a synonym, so feel free to substitute clicely triples for monads if you don't feel you sound confusing enough.
Now I'm going to show you a simple use case for monads. I've already established that we are using lists for most of these examples. So I'm going to show you quite simply how to use the list monad. And our use case is going to be the element of harmony.
As we all know, each of the main six ponies is associated with her own element of harmony. So I have essentially just created an HTML list. An ordered list of ponies.
With sub lists containing each ponies corresponding element of harmony. I want to take that list as an input parameter for a function and return the list of elements of harmony. Which means that I should be... Let's just look at the list and explain that properly.
The idea is that I need to pick out the children of that list. And then the grandchildren of that list should be the element of harmony. Because the children should be each pony. And each pony has a child of its own being the element of harmony. If you know HTML, this should be obvious.
Otherwise just take my word for it. It's a tree structure. I have a children function. It takes a DOM element. That would be an HTML tag. And it returns a list of the children of that element. Let's check that that works.
I'm picking out the list of ponies from the previous slide. These are HTML slides. By its ID. And storing that in ponies. And then I'm calling children of ponies. So ponies is the whole list. That is the element that goes into this function. And it should return each pony in a list.
And it does! Yay! So hey, you guys remember composition, right? So obviously to get the grandchildren we just compose children with itself. So compose children and children. And just call that on ponies.
Nah. That doesn't work. Why doesn't that work? Anybody care to guess? Because children takes one element in. Outputs a list of elements. So for the second call to children. This gets a list and thus crashes horribly.
Now the idea of the list monad is that it can take a function like that and kind of, what's the term, can you say list that into the list monad? At least the list monad is in charge of turning this function into something that would be composable given the case of one element in a list of elements out.
Now monads consist of two things in the simplest forms. The unit function which takes a value and returns a list of values in this case. The idea is that it turns the case of the one element into something that would be composable
meaning just a list containing that element. The unit function bind. This is the other part. The bind, that's a whole other function
that takes the function that you want to make composable which, as we know, takes a value that is just one element so not a list of any, but just any and returns a list. This is exactly the signature of the children function
except generalized. Now, the bind function should return a function that takes an argument list, which is a list instead of the value, which is just one item, right? And it returns the list, obviously.
Wow, I almost ran into characters. I did, in fact, run into characters. Yeah, okay. I ventured into Allman style indentation by accident.
This creates a function which takes the expected list and we're going to have to do some iteration here. We start out with an empty list and we need an iteration variable and a for loop and for each element of the input list
we concatenate onto out the result of calling function on that list. This looks a bit like the generalized the function used to create the generalized MapReduce thing, right? Never mind.
The idea is that for each element of the list coming in we essentially expand that element into a list using the input function and when we are done doing that, concatenating each list together
we get a list of all that and we just return that. Trust me, this is mainly composable. Shall we check? So that means that, first of all, we need to turn ponies which is just one element
into something that is suitable for inputting into the composable function which takes a list and, of course, turning the element ponies into a list means just making a list of the one pony's element which we do using unit. Now we use bind to make children composable twice
and now, this doesn't quite work either, does it? But at least it's not crashing and it is actually returning the grandchildren. Problem is, in HTML sublists actually are lists
and then there are items inside that list so we're not looking for the grandchildren we are looking for the great grandchildren. Now, that gets us the element of harmony and what I just did there was using the list monad
to turn the children function into something that will be composable repeatedly and thus, ladies and gentlemen you understand monads, don't you? Thing is, the list monad is perhaps one of the very simplest forms of a monad
and they get a lot more interesting so go out and read those monad tutorials and I'm sure you'll be enlightened, yeah? Anyway, because if even that doesn't do it for you Haskell never stops giving. My favourite part of Haskell is this thing called Zygote
Zygote isomorphic preformorphisms that is a weird thing in Haskell I love that and that text you see there that is all the documentation you get this is in, I believe it's in the Haskell standard library at this point which is totally awesome
so this, in addition to some code examples that is all the documentation it is assumed that a Haskell developer would need which makes it even more awesome in case you're wondering a Zygote isomorphic preformorphism is a preformorphism with both zygomorphic and histomorphic properties
right it's obvious, come on right, so if even that doesn't do it for you there's always logic programming thank you very much
if you want to check out the slides or play with that replica thing that I have going there the link at the bottom that is for the live slides you can just open that in your browser and play with the code right questions
yeah, I figured I don't usually get questions, first one sure, you can do that because yeah, this is JavaScript I was actually trying to be kind
and do it using a for loop because I figured most people wouldn't know for loops not necessarily everybody I mean, you guys look very smart but probably some of you don't really know too much about recursion or those people in the other room, perhaps, I don't know so, yeah, you could certainly do it by recursion mind you that JavaScript doesn't do take or optimization
so you might play in the stack doing that but, yeah other questions? sorry, can you as a Java programmer
good lord, I'm so sorry so, I'm going to repeat the question is there a hipster trick that you want to repeat the talk?
I'm sure you can guess this in a bit, don't worry you look very smart yeah, because I'm doing this to make myself look smart but that should be obvious, yeah? I just said zyger-histomorphic pre-promorphism do you know how much time I had to practice to be able to pronounce that? you have no idea
so, yeah, of course this is a hipster trick more questions? we have about three minutes left
but they are being obscure yeah is there going to be real functional programming for the masses without us having to become academic?
so the question essentially is is it possible to formulate a language that is actually understandable describing all these concepts? I don't understand why you want to do that well, certainly people have tried I mean, just the other day
I learnt from Don Seim that monad comprehensions in F-sharp are deliberately called, what are they? asynchronous workflows that's an inaccurate description of asynchronous workflows where essentially they are monads they are kind of a euphemism for monads and that is becoming quite popular
in Scala, monad comprehensions are called for comprehensions because that makes it less threatening so certainly people are trying to take the edge of the language of category theory but I don't see the point I mean, would you want muggles flooding your wonderful ivory tower?
I certainly wouldn't in F-sharp they are actually called computation expressions computation expressions I guess that would be the more generalized form just don't mention asynchronous workflows and that smells like an Iron Man ad to me or a promised man, I don't know
right, anymore? Did you consider using your monad for the ugly null-checking you did in the middle just an actual, live, usable example of a monad? Yeah, the question is did I consider using a monad instead of the null-check combinator? I certainly could have I mean, that is another very simple example of a monad
the maybe monad, exactly yeah, that is a very good use case for monads of course, you can also just do a null-check but in Haskell that isn't the way to do things obviously, that would be too easy yes? I'm looking forward to the talk about continuation passing style
yeah I'm not sure, I mean, that sounds a bit the question by the way was the comment was that he was looking forward to the talk on continuation passing style I think those schemas aren't to be trusted so I'm not going to do that right, we are essentially out of time so unless somebody has a very short question
I'm going to call that a day thank you very much for coming