No Silver Bullets in
Functional Programming
Brian McKenna
Atlassian
Almost always functional programming
Australia
There's no such thing as a silver bullet...
... there is no single development, in either technology or
management technique, which by itself promises even one order
of magnitude improvement within a decade in productivity, in
reliability, in simplicity.
...
Hence, although I strongly support the technology transfer and
curriculum development efforts now underway, I think the most
important single effort we can mount is to develop ways to grow
great designers.
Fred Brooks, 1986
The differences are not minor - it is rather like Salieri and Mozart.
Study after study shows that the very best designers produce
structures that are faster, smaller, simpler, cleaner and produced
with less effort. The difference between the great and the
average approach is an order of magnitude.
Fred Brooks' experience as of 1986:
No 10x tools
But 10x programmers
1. No tool will fix all productivity/reliability/simplicity problems
2. No tool strictly better than another
Availability vs consistency
Space vs time
Git vs Mercurial
Emacs vs Vim
YAML vs JSON
Functional programming
(10 + 30) * 2
40 * 2
80
Referentially transparent expressions can be replaced with the
value that they evaluate to.
Functions are a way of creating referentially transparent
expressions.
Functional programming is programming with referentially
transparent expressions.
Reuse
println("Hello");
println("World");
println("Hello");
println("World");
val x = {
println("Hello");
println("World");
};
x;
x;
Refactoring
bind(getCredentialsProvider, credentials => {
val regions = Regions.fromName(streamRegion);
val config = makeClientConfiguration(regions);
val client = kinesis(credentials, config, regions);
val proxy = kinesisProxy(credentials, client);
getShardList(proxy);
});
val regions = Regions.fromName(streamRegion);
val config = makeClientConfiguration(regions);
bind(getCredentialsProvider, credentials => {
val client = kinesis(credentials, config, regions);
val proxy = kinesisProxy(credentials, client);
getShardList(proxy);
});
Equational reasoning
def traverse[A](l: List[A], f: A => IO[Unit]) =
l.foldRight(
(a, acc) =>
bind(
f(a),
_ => acc
),
point(unit)
);
traverse(["Hello", "World"], println);
["Hello", "World"].foldRight(
(a, acc) =>
bind(
println(a),
_ => acc
),
point(unit)
);
bind(
println("Hello"),
_ =>
["World"].foldRight(
(a, acc) =>
bind(
println(a),
_ => acc
),
point(unit)
)
);
bind(
println("Hello"),
_ =>
bind(
println("World"),
_ =>
[].foldRight(
(a, acc) =>
bind(
println(a),
_ => acc
),
point(unit)
)
)
);
bind(
println("Hello"),
_ =>
bind(
println("World"),
_ => point(unit)
)
);
bind(
println("Hello"),
_ =>
println("World")
);
println("Hello");
println("World");
Some benefits for humans:
Reuse
Refactoring
Equational reasoning
Compare the alternatives
Functional programming
Imperative programming
Object-oriented programming
Functional programming
Imperative programming
Object-oriented programming
In short, Haskell is the world's finest imperative programming
language.
Simon Peyton Jones, 2000
Functional programming
Not functional programming
Values
Side-effects
Benefits of side-effects
Argument to moderation
"Mostly functional" programming does not work.
...
The idea of "mostly functional programming" is unfeasible. It is
impossible to make imperative programming languages safer by
only partially removing implicit side effects. Leaving one kind of
effect is often enough to simulate the very effect you just tried to
remove. On the other hand, allowing effects to be "forgotten" in a
pure language also causes mayhem in its own way.
Erik Meijer, 2014
Middle-ground between a lie and the truth is a lie.
Middle-ground between a side-effect and a value is a side-effect.
Tooling
In theory, functional programming only has benefits.
In practice, tools have trade-offs.
type Effect[a]
= WriteLine String a
| ReadLine (String -> a)
program = {
writeLine("Hello, what's your name?");
s <- readLine
writeLine("Hello " + s);
};
blink :: Atom ()
blink = do
on <- bool "on" True
period timeout . atom "blinkOn" $ do
call "avr_blink"
on <== not_ (value on)
Sunk cost
We have invested a lot of time and effort into using side-effects.
We have received no inherent benefit over functional programming.
We need to beware of putting any more effort into side-effects.
Success
Shift the conversation:
We already do functional programming.
If you want to use side-effects, the burden of justification is on you.
Don't fall into the "everything is about trade-offs" trap:
Functional programming gives significant benefits over side-effects.
Side-effects give zero benefits over functional programming.
We should consider side-effects to be legacy.
Functional programming should be our future.

No Silver Bullets in Functional Programming by Brian McKenna