Beauty and/or Elegance in
Functional Programming
Amr Hassan
Silvia Pina
Introduction
Prelude
DISCLAIMER: Most of the time when the presenters of this talk are saying “functional
programming” they actually mean typed functional programming.
DISCLAIMER: We use the terms: code, source code, program and software
interchangeably. They are all intended to mean source code.
Beautiful Code?
Good Software
What is ultimate definition of good software?
Good Software
What is ultimate definition of good software?
Correct software
Good Software
What is ultimate definition of good software?
Correct software
That can’t be all.
Maintaining Unfamiliar Software
>> git clone git@github.com:foocorp/bar-service.git
Maintaining Unfamiliar Software
1. Code is very “good”.
Maintaining Unfamiliar Software
2. Code is accompanied by extensive well-written up to date docs.
Maintaining Unfamiliar Software
3. Code is neither “good” nor well-documented.
Maintaining Unfamiliar Software
Let’s back up for a bit...
What is Beauty?
The quality or aggregate of qualities in a person or thing that gives
pleasure to the senses or pleasurably exalts the mind or spirit
-- Merriam-Webster Dictionary
Interpretations of Beauty
Beauty in Ancient Egypt
Ancient Egypt: Earliest system of proportions
Copyright © [Pentti Routio]
Beauty in Ancient Greece
Ancient Greece: Perfect order, proportion, symmetry
Beauty in Ancient Greece
Ancient Greece: The Golden Ratio
Copyright © [Canva]
Beauty in the Golden Ratio
Beauty in the Golden Ratio
Beauty in the Golden Ratio
Copyright © [WideWalls]
Minimalism and Beauty
“Less is more”
-- Mies van der Rohe (1940s)
Minimalism and Beauty
“Perfection is attained not when there is nothing
more to add, but when there is nothing more to
remove.”
--Antoine de Saint Exupéry (1939)
Beauty in Mathematics
Beauty in Mathematics
“Nothing without understanding would ever be
more beautiful than with understanding”
-- Plato (ca 400 BC)
Beauty in Mathematics
“Mathematics, rightly viewed, possesses not only
truth, but supreme beauty.”
-- Bertrand Russell (1919)
Experiencing Beauty in Mathematics
Beauty in Mathematics
Euler’s identity
Beauty in Mathematics
Ramanujan’s infinite series for 1/π
What do mathematicians usually describe as
beautiful?
Beauty in Mathematics
Concise
Beauty in Mathematics
Has minimum additional assumptions
Beauty in Mathematics
Well-defined enough to be used as part of
other proofs / formulas
Beauty in Mathematics
Simple. Clear.
Programming == Maths?
Programming == Maths?
Strongly-typed programs
are proposition proofs
Beauty in Code
def isElegant(code: AST): Boolean = ???
Beautiful or Elegant?
Beauty / Elegance in Code?
Beauty / Elegance in Code?
Separation of concern
Beauty / Elegance in Code?
Non-repetitiveness
Beauty / Elegance in Code?
Conciseness
Beauty / Elegance in Code?
Modularity
Beauty / Elegance in Code?
Reusability
Beauty / Elegance in Code?
Simplicity
Beauty / Elegance in Code?
● Separation of concern
● Non-repetitiveness
● Conciseness
● Modularity
● Reusability
● Simplicity
(Some of these are overlapping or direct result of each other, but we’ve tried to be as
exhaustive as possible.)
● Separation of concern
● Non-repetitiveness
● Conciseness
● Modularity
● Reusability
● Simplicity
● Concise
● Has minimum additional
assumptions
● Well-defined enough to be used as
part of other proofs / formulas
● Simple. Clear.
Beauty in Code
Copyright © [Brandi J. Clark]
What’s a Good Mathematical Definition of Computing?
λ
Functional Programming
What is Functional Programming?
Functional Programming
It’s lawful transformations on data.
What is Functional Programming?
Functional Programming
It’s programming using immutable data,
and pure functions.
Functional Programming
It’s programming using immutable data,
and pure functions.
Immutable Data
val x = 42
val xs = List(8, 15, 16, 23, 42)
val ys = 4 :: xs
Pure Functions
Pure Functions
x ↦ f (x)
Every
Single
Time
Functional Programming
λ
Conciseness in Functional Programming
def twice(f: Int -> Int): Int -> Int =
(x => f(f(x)))
val addTwelve: Int -> Int =
twice(_ + 6)
Conciseness in Functional Programming
case class Robot(name: String, canFly: Boolean)
val robots = List(
Robot("WALL·E", true),
Robot("Bender Bending Rodríguez", false),
Robot("R2-D2", true),
Robot("T-800", false)
)
val canFly: Robot => Boolean = _.canFly
val flyingRobots = robots filter canFly
val bender: Option[Robot] = robots find (_.name.startsWith("Bender"))
Simplicity in Functional Programming
Single-state values
Simplicity in Functional Programming
Parametricity
Simplicity in Functional Programming
def process(x: Int): Int
Simplicity in Functional Programming
def process(x: Int): Int
(232)(2^32) possible implementations
Int is just too powerful
Simplicity in Functional Programming
Parametricity
Simplicity in Functional Programming
def process[A](a: A): A = ???
Simplicity in Functional Programming
def process2[A, B](a: A, f: A => B): B = ???
Simplicity in Functional Programming
def process3[A: Show](a: A): String = ???
trait Show[A] {
def show(a: A): String
}
Simplicity in Functional Programming
Parametricity
Modularity in Functional Programming
f: x ↦ y
g: y ↦ h
( g ∘ f ): x ↦ h
Modularity in Functional Programming
def andThen[A, B](f: A => B, g: B => C): A => C =
(x => g(f(x)))
(Not exactly how andThen is actually implemented for functions in Scala)
Modularity in Functional Programming
type Json = JsonNumber | JsonString | JsonBool | JsonNull | JsonArray | JsonObj
val encode: Json => String = { … }
val decode: String => Option[Json] = { … }
case class Uuid(hex: String)
val encodeUuid: Uuid => String = (_.hex) andThen JsonString andThen encode
Val decodeUuid: String => Option[Uuid] =
decode andThen { case Some(JsonString(v)) => Uuid(v); case _ => None }
Dotty Sum
Type Syntax
Separation of Concerns in Functional
Programming
Separation of Concerns in Functional Programming
Category theory abstractions
Separation of Concerns in Functional Programming
case class Permissions(read: List[Resource], write: List[Resource])
Separation of Concerns in Functional Programming
val awkwardCoarse: List[Permissions] = List(perm0, perm2)
Separation of Concerns in Functional Programming
class Permissions {
def combineWith(other: Permissions): Permissions =
{ … }
}
Separation of Concerns in Functional Programming
implicit class PermissionsOps(perms: Permissions) {
def combineWith(other: Permissions): Permissions =
{ … }
}
Separation of Concerns in Functional Programming
trait Monoid[A] {
def empty: A
def combine(a1: A, a2: A): A
}
Separation of Concerns in Functional Programming
object Permissions {
implicit val monoid = new Monoid[Permissions] {
def empty: Permissions = { … }
def combine(p0: Permissions, p1: Permissions): Permissions =
{ … }
}
}
Separation of Concerns in Functional Programming
val nicerCoarse: Permissions = perm0 |+| perm1
val reducedNicely: Permissions =
List(perm0, perm1, perm2).combineAll
Conciseness / Non-repetitiveness
Simplicity
Modularity
Separation of Concerns
Copyright © [Percussion Software]
Beautiful Code and Quality Metrics
http://bit.ly/10jbfr6
Beautiful Code and Quality Metrics
Strong typing achieved less defects than weak typing
Beautiful Code and Quality Metrics
Among functional languages,
static typing achieved less defects than dynamic typing
Beautiful Code and Quality Metrics
Functional languages get somewhat better results than procedural
languages
In Conclusion
Thank you
@shirurup
@superamr
We didn’t mention referential transparency or monads even once!

Beauty and/or elegance in functional programming

Editor's Notes

  • #3 Hello everyone, Amr: My name is Amr. I’m a software engineer at Zalando. I use Scala to build microservices for Brand Solutions. Silvia: Hello, my name is Silvia, and I do exactly the same thing. Amr: We’re here today to talk to you about beauty, elegance in code, and functional programming. And how those three things relate.
  • #4 For starters we just want to get a couple of disclaimers out of the way..
  • #5 How many of you has been in this situation. You’re working on a project. It’s business as usual. You run into a particular problem. You spend a while thinking about the best way to handle this problem. And then you build a solution in. And after validating that it’s correct, Sometimes, you get this little moment, when you kick back and marvel at what you have created And you think This is the most beautiful code ever!
  • #6 Enough with the chit-chat. Let’s cut to the chase.. What is without a doubt the ultimate definition of Good software?
  • #7 Most of us would say: Correct software. And I would totally agree with this. For the sake of the discussion, let’s assume that we figured out how to do that. It’s not an issue any longer.
  • #8 But that can’t be all! We need to maintain this correct software. We need to augment it with new functionality was not considered at its inception. We probably will need to change how it’s doing something. Because this is the real world.. Requirements change..
  • #9 There come situations When you have to change something about a software project that you’re not particularly familiar with. The situation usually goes likes this: You go in the source code, You locate the part that you’re interested in You start reading it because you need to understand it before you could modifying it. Your situation is one of three:
  • #10 The code is so “good”, that it’s very easy to simply read it and understand everything that it’s doing.
  • #11 The code is accompanied by extensive well-written “up-to-date” documentation it’s just a matter of reading the docs, matching the behaviour to respective code lines
  • #12 You have neither and you’re on your own. This is the least favorable situation But unfortunately it’s very frequent.
  • #13 A lot of times when you’re in this situation, Even if you don’t admit it to yourself as you are trying to understand the code In the back of your mind at least you start thinking in terms of less-concrete metrics of software quality. You might start questioning the maintainability of this software.. And if you’re one of those who answered yes to the earlier question, You might even catch yourself complaining about the ugliness or the lack of code elegance in this project
  • #14 But can we really use such terms to talk about code? Let’s back up for a bit and look into what beauty or ugliness means here...
  • #15 A quality present in objects, that gives an experience of pleasure, joy, and satisfaction to the perceiver. This is the first part of the definition: something that gives pleasure to the senses. Beauty is found in art and in music. We can intuitively enjoy this kind of beauty immediately, because it’s built in our nature. Beauty is also in things that are not immediately perceived by us. This is the second part of the definition: something that appeals to the mind or spirit. We’ll explore that later on. We will now focus on the first part.
  • #16 Beauty has been recognized as a core value throughout history and different cultural traditions. The standards of beauty differ greatly from one period to another, and from one culture to another.
  • #17 It's theorized that the thin lines visible on Ancient Egyptian wall sculptures are part of a widely used system of proportions based on instructions for wall decorations. These instructions date as far back as 2800 BC, and they are the earliest mention of beauty in history.
  • #18 In Ancient Greece (ca 500 BC) Pythagoras believed that he discovered that the absolute definition of beauty in nature and the universe is based on precise mathematical laws that govern their proportions and symmetry.
  • #19 He was mainly talking about the golden ratio. The ratio of a and b is the same as the ratio between their sum and a (the larger of the 2) It is a constant value of approximately 1.618 And the fact that a lot of things that are considered beautiful in nature (including humans) seemed to follow this ratio.
  • #20 Since the Pythagoreans started popularizing this notion of the Golden Ratio, several artists and architects started applying this ratio to their works of art and architecture. An example of this is the famous Venus de Milo
  • #21 In rectangular form, the golden ratio makes this rectangle. a is the height and the sum of a and b is the width of this rectangle, and they follow the ratio we saw before. This is the so called golden rectangle.
  • #22 You can find examples of this ratio in Greek architecture, like here in The Parthenon, where its front view follows these exact proportions.
  • #23 If we jump ahead to modern times, We find works of architecture like this here: Farnsworth House designed by Mies van der Rohe He is a proponent of minimalism in architecture, and the source of the phrase: “Less is more” Which is the trend in the minimalism movement in architecture and design where the subject is reduced to only its necessary elements. And that was its main source of beauty. And they found that to be more appropriate to these modern times.
  • #24 We find the same idea expressed in the famous quote by Antoine de Saint Exupéry’s words “perfection is attained not when there is nothing more to add, but when there is nothing more to remove”.
  • #25 So how close are the experiences of beauty in art and beauty in mathematics? On the one hand they come from different sources: we perceive art with our senses, and this is somewhat more immediate while to perceive beauty in mathematics we need to understand what an expression or proof means. On the other hand, both forms of beauty can elicit in us an emotional response of something that is pleasant.
  • #26 This idea goes back as far as Plato, who he said: “Nothing without understanding would ever be more beautiful than with understanding”. According to Plato it’s not just another equal kind of beauty, but one that provides even more reward. And this is why for him mathematical beauty was considered the highest form of beauty it comes from the intellect alone and it is concerned with eternal and immutable truths.
  • #27 Many additional authors have talked about beauty in mathematics too, comparing the experience of beauty in mathematics to that from art forms. “Mathematics, rightly viewed, possesses not only truth, but supreme beauty.”
  • #28 This is also backed by neuroscience experiments, like here in this study done by Semir Zeki, in which: Using a brain scanning technique, it showed that the same areas of the brain are activated by the experience of mathematical beauty and the ones activated by the experience of the more immediate sources of beauty like art and music.
  • #29 Mathematicians have been calling mathematical formulas and proofs as “beautiful” for a long time. Euler’s identity equation has long been the universal winner of all beauty contests in the mathematical community: Because of: It is simple to look at and yet considered incredibly profound in meaning It includes the 5 most important mathematical constants (0, 1, pi, e, i) It shows how the power of abstraction enabled the simple representation of otherwise very complicated concepts like irrational and imaginary numbers
  • #30 By contrast, an example of an equation judged as ugly is Ramanujan’s infinite series for 1/π:
  • #32 Concise Non-repetitive. without redundant calculations.
  • #33 Has minimum additional assumptions Exactly as many assumptions as it needs.
  • #34 Well-defined enough to be used as part of other proofs / formulas
  • #35 Simple. Clear. Only as complicated as it has to be, not a bit more.
  • #36 Right.. So that was mathematical beauty. But is programming a mathematical discipline?
  • #37 Some believe that this is the case. And if you do, it should be easy to convince yourself that all of those beauty characteristics translate.
  • #38 But if you don’t, Then we should look into what software developers consider What elegant code is.
  • #39 Just to clear out some of the confusion. I strongly believe that we tend to say “elegant” more frequently than “beautiful” when we talk about code. Probably because we want to sound less emotional, and more professional about it. But for all intents and purposes, I believe we mean the same thing.
  • #40 So what do software developers consider as elegant code? We asked around and the responses were quite familiar. It’s code that has the following properties:
  • #41 Separation of concern The property of: focusing on small problems one at a time
  • #42 Non-repetitiveness The DRY principle
  • #43 Conciseness The property of: writing only essential code and incurring minimal accidental complexity
  • #44 Modularity The property of being easy to adapt and extend
  • #45 Reusability The property of being easy to reuse in different contexts
  • #46 Simplicity Simplicity is quite tricky to define. But we happen to agree with the following definition of simplicity: It is having a limited number (that is as small as possible) of concepts that you need to account for in your head in order to “read”/understand a piece of code well. So naturally, if you break down your problem into orthogonal concerns, and solve each only once in a way that can be used across your program you achieve code simplicity! Because there are only so many discrete things to account for. This makes sense. Since this is the preferred way for our brains to ingest complex thoughts. By repeatedly breaking it down into smaller and smaller ideas.
  • #47 We know that Some of these are overlapping or direct result of each other, but we’ve tried to be as exhaustive as possible.
  • #48 If you put the two lists next to each other, And sort of cover the headers with your hand, you’ll probably have a tough time telling which list is which…
  • #49 It seems that, Whether you like or not… Your expectations of elegant code are very similar to mathematician’s expectations of beautiful maths. So why don’t you give in, and embrace that you should be looking at math for good programming discipline?
  • #50 What’s a good beautiful mathematical definition of computing? Of course, our favourites: lambda calculus, and category theory. But we won’t go much into mathematics today (we’re not mathematicians either).
  • #51 Instead, the closest we can get to designing our code bases as math, is through Functional Programming.
  • #52 What is functional programming thing we keep mentioning?
  • #53 You could define functional programming as “lawful” transformations on data. But that’s too abstract. Doesn’t sound very useful.
  • #54 Let’s try again.
  • #55 How about this.. Functional programming is programming using immutable data, and well-typed pure functions.
  • #56 That sounds better. We could work with that right away. Let’s dig deeper into what that means!
  • #57 What’s immutable data? Immutable data is very simple. It is when your data is frozen in a single state from the moment it is created and until the end of your program. Here we can see three examples of immutable data. On the third line I create a modified version of my immutable value and assign it to a new name. And my original value stays intact.
  • #58 Pure functions are even a simpler concept than that. A pure function is a box. Its job is to map its well-specified input to its well-specified output
  • #59 Given the same input, it should output the same value. Every. Single. Time.
  • #60 So that is what functional programming is.. Sounds pretty easy.. You can probably already see how much prettier your code could be if it was written this way. If you still don’t see it, let’s try to explore that a bit further..
  • #61 How does functional programming approach conciseness and non-repetitiveness? Functional programming builds on top of functions as the primitive building blocks of a language. That naturally gives rise to the concise abstraction that is higher order functions. A higher-order function is one that accepts a function in its parameter and/or returns one as a value. That’s where we get to start doing interesting things with functions prior to evaluating them.
  • #62 Really cool examples of higher-order functions in action are in the Scala standard collections library In which you can see how by leveraging higher-order functions, we can accomplish so much with very little verbosity, And with very little repetition overhead. In the the filtering and the finding operation, all I did was define the one bit of extra logic that the standard library did not know about, Which is how I chose the elements in my new sublist and how I picked the one instance out of the list. The rest of the logic for accomplishing the filtering and finding I got to reuse from the definition of the standard library. This is pretty concise indeed..
  • #63 The next aspect of code elegance we’ll look into is Simplicity. And simplicity is prevalent in functional programming. You can immediately notice it by the fact that your data is immutable and it will always have a single state. And this is a huge load to take off of your mind the idea that values can change anytime and you need to manage that. Big win for simplicity.
  • #64 My favorite part that I always love to bring up is parametricity. What is Parametricity? Let’s see a code example first.
  • #65 Can you tell what this function is doing? Or how you could possibly implement it, given only the type signature.
  • #66 It’s very difficult. Because in Scala there are (2^32)^(2^32) possible implementations. Int is too powerful. And this function is exponentially more powerful than one Int.
  • #67 Parametricity is all about providing code with just enough power to accomplish the job, and nothing more. The fact that we give up only the minimal amount of power to a function implementation gives us back way more power in reasoning about what a function can actually do. Let’s see an example of that..
  • #68 In this example, If you ignored that Java would let you do hasCode() and toString() on any object And forget that nulls exist, How many ways can you implement that function? [Pause for audience participation] There is only one possible implementation of process. The identity function. This is a pretty good example of least amount of power, and it’s actually useful. It’s not a toy implementation. We actually make use of the identity function in our day-to-day code.
  • #69 In this second example, you’re given a little bit more power. You’re provided with a function that transforms A into B, and you’re asked for a B. There is also only one way you could implement that. You can always guarantee this, just from looking at the function type signature.
  • #70 In this example, I provide my function with quite more power. The function can now grab a Show typeclass instance for A. You can get a String for any A. The fact that we’ve given up this much power shows up immediately in our decreased ability to predict what this function can do. Because String type is powerful enough that you could construct any String value on the fly and pass it back. But at least we make sure that you can’t do anything else with A in this case.
  • #71 The take-away from this, is By limiting the power of your code, you keep the number of concepts you have to account for during the implementation and during the usage as small as possible. And that is quite close to the definition of simplicity we talked about earlier.
  • #72 Next up, modularity. In functional programming you build your code out of minimally powerful small units of logic. And those can only do so much by themselves. So you are sort of put in a situation where You have to compose or you can’t really accomplish much. And that already structures your code in a very modular fashion, even if you didn’t intend it to be so.
  • #73 Simplest form of composition in functional programming is through composing the simplest unit of logic. Functions. When you think about them your functions as pure transformations of typed values, they turn into these pipe-like structures that you can assemble one after another And the functionality of the whole is more than the sum of its parts.
  • #74 Here’s an example of the kind of modularity provided by composition, Functional composition in this case. I have managed to condense my JSON functionalities into two functions. One to encode one of my JSON primitives into a String And one to optionally decode back from a String. Using those I can build encoding and decoding logic for any custom data structure in my code, by simply piping together appropriate calls to functions. [EXPLAIN CODE] You can see how very modular this is. You can extend this with very little effort to be able to encode or decode any other custom data structure you might have.
  • #75 Last but not least, Separation of Concern. There are a lot of approaches for achieving Separation of Concern in Functional Programming. Just because we’re pressed for time, we’re going to talk about only one of them.
  • #76 It is, borrowing useful constructs right out of Category Theory.
  • #77 Here’s a real world example, In your code for one reason or another, you would up with this representation for a security Permission. It contains by itself collections of resources that it’s allowed to read and modify. And then pops the use case of having to merge multiple Permissions into a coarser representation
  • #78 We could right away start packing Permissions in an already existing collection type, like List. That gets awkward pretty quickly. Because it’s too powerful. And, your function signatures that deal with Permissions would have to account for the fact that permissions can be of either Permissions type or a collection of Permissions. That’s code smell.
  • #79 A better way to accomplish this is to create your own combination function that combines two of them. So you either add it to the Permissions class if you can modify that,
  • #80 Or find a way to enrich it with that function.
  • #81 Or you could subscribe to an already existing abstraction from Category Theory, The Monoid. Implemented usually via a typeclass. You can get this definition from a library like Cats or Scalaz for Scala.
  • #82 And then define the logic of combining two Permissions instances in a totally separate manner from how it’s used.
  • #83 Having done that, You can start using it in different ways without worrying about implementing. As an added bonus, you can totally reuse ways of how combine instances of your data structure. If you make use of libraries like Cats or Scalaz. You get these two functionalities for free, Once your Monoid instance for your data structure is in scope. You can combine two instances using this operator. Or reduce any collection type made of these instances. This purely possible due to the separation of where the logic of combination is implemented And where it’s used.
  • #84 So. Those were our thoughts on how Functional Programming is pushing us towards aspects of code elegance. There are plenty more that we couldn’t cover in such limited time. We hope that we have at least piqued your interest about the subject. And that you would continue learning more about it, because there is a lot more to learn.
  • #85 The question now is: Is it just about feelings and happiness? Or is there a practical real-world outcome of elegance in code?
  • #86 There was a large scale study of programming languages and code quality on Github. It involved more than 700 projects in 17 different languages. The GitHub data was used to determine the effects of language features on defect occurrence using a variety of tools. The methods were: multiple regression modeling, clustering, and visualization. The main findings of this study are:
  • #87 Strong typing achieved less defects than weak typing
  • #88 Among functional languages: static typing also achieved less defects than dynamic typing
  • #89 Functional languages got somewhat better results than procedural languages
  • #90 In conclusion, We’ve explained how following the principles of functional programming pushes developers towards achieving more elegance in code. That indeed makes the ones of us who appreciate elegance in code happy. And according to the study just mentioned, it is also more likely to produce code with less defects. Which is a win-win!
  • #91 Thank you for your attention. Hope you enjoyed the talk. If you have any questions, you can find us around here all day.