CoRecursive: Coding Stories
Tech Talk: Design Principles From Functional Programming
Guest: Runar Bjarnason
Host: Adam Gordon Bell
Date: January 10, 2018
Overview
In this episode, Adam Gordon Bell interviews Runar Bjarnason, co-author of Functional Programming in Scala, about the core ideas and real-world impact of purely functional programming. The conversation covers the fundamentals of functional programming, its advantages in modularity and compositionality, practical approaches for handling effects and exceptions, abstraction as a path to precision, and reflections on learning and teaching this software paradigm.
Key Discussion Points
1. Purely Functional Programming: What and Why?
- Definition & Principle:
- Functional programming is “programming with functions only,” specifically mathematical functions that take an input, return an output, and “don’t do anything else.”
"Purely functional programming is programming with functions only. So when I say functions, I mean mathematical functions." – Runar (01:28)
- Functional programming is “programming with functions only,” specifically mathematical functions that take an input, return an output, and “don’t do anything else.”
- Side-Effects & Modularity:
- Side effects are avoided—if a function needs to interact with the outside world (like writing to disk), it instead returns an instruction or “little program” that the runtime executes.
- This style enforces constraints, making program modules more easily composable and reliable.
"Functional programming solves the problem of modularity and compositionality... the superpower of functions is that they compose." – Runar (02:37)
2. Architecture Implications
- The resulting architecture: the entire program becomes a single expression to be evaluated by the runtime.
"Your whole program will be a single expression, and then to evaluate that expression will be to run the program." – Runar (03:40)
- Constraints introduced in functional programming lead to more reliable, predictable software systems, fostering stability especially in large systems.
3. Language Choice & Abstraction
- Scala is not Required:
- Any language supporting first-class (or even workarounds for) functions can support functional programming.
"Scala is absolutely not required... we were doing functional programming back in the day in Java..." – Runar (05:37)
- Any language supporting first-class (or even workarounds for) functions can support functional programming.
- Abstractions Enable Power:
- Abstracting recursion via “fold” functions avoids repeating patterns, providing both higher order and parametric polymorphism.
4. Key Functional Concepts Explained
- Referential Transparency:
- A property by which an expression can be replaced with its value without changing the program.
- Enables reasoning, substitution, and equational reasoning throughout a program.
"Referential transparency is the property that... the result of evaluating the expression is going to have the same meaning as the expression that you started with." – Runar (08:13)
- Handling IO and Effects:
- IO is modeled as “values” returned to the runtime, not performed directly in the program.
"IO effects never happen inside of your program, they happen outside in the runtime environment." – Runar (10:23)
- IO is modeled as “values” returned to the runtime, not performed directly in the program.
- Immutability:
- Mutation counts as a side effect and breaks referential transparency.
- Local mutations can be safe if encapsulated (e.g., ST monad for local, safe mutation).
"Mutation is a side effect. It's not referentially transparent." – Runar (12:45)
5. Modularity, Composition, and Data Structures
- Functions are the ultimate module: always have clear input and output, can be composed easily.
- Linked lists are idiomatic in FP due to immutability. Under-the-hood mutation may be used for performance, but is abstracted away.
- Concepts like “fold,” “map,” and parametric polymorphism enable working generically across many types.
6. Exceptions, Nulls, and Explicit Error Handling
- No Exceptions:
- Throwing breaks transparency. Instead, represent errors as explicit types (e.g.,
Option,Either)."Exceptions absolutely do violate the reference to transparency. And if you throw an exception inside of a function, it's no longer a function because it's not returning a value." – Runar (23:51)
- Throwing breaks transparency. Instead, represent errors as explicit types (e.g.,
- Option vs Null:
- Null is unsafe, not explicit in the type.
Option/Mayberequires explicit handling and can be “folded” (pattern matched), not just dereferenced blindly.
- Null is unsafe, not explicit in the type.
- Either for Rich Errors:
- Can return a meaningful error or a value, making error handling explicit and safe.
7. Performance Topics
- Potential Overhead:
- FP data structures may use more heap or stack, especially with recursion and function objects, but techniques like tail call elimination and trampolining can help.
- Implementation Details Hidden:
- Underlying mutable structures can exist without breaking purity if the interface remains functional.
8. The Value of Constraints & Abstraction
- Constraints Are Liberating:
- By limiting what a function can do, reasoning and understanding become dramatically easier.
"Constraints liberate, man." – Runar (38:40)
- By limiting what a function can do, reasoning and understanding become dramatically easier.
- Abstraction Yields Precision:
- Parametric polymorphism (generics) constrains possible implementations, increasing precision.
"Abstraction is really about going to a higher semantic level where we can talk... in a language where we can be absolutely precise." – Runar (41:49)
- Example: The polymorphic identity function can only ever return its input because it knows nothing else about the type.
- Parametric polymorphism (generics) constrains possible implementations, increasing precision.
9. Teaching & Learning Functional Programming
- The Functional Programming in Scala book was designed as a “work through” book packed with exercises to build practical understanding by doing, not just by reading.
"In order to really learn something, you have to make it a part of your work... that led us to the idea of having a book that you don't just read. It's a book that you do." – Runar (45:49)
10. Vision for the Future
- If all software were written in this style, programs would be more understandable, maintainable, and composable.
“We'd be able to compose software that wasn't necessarily written to be used together. ...With pure functions, you can always kind of snap them together.” – Runar (49:28)
Memorable Quotes & Timestamps
- On what functional programming is:
"Purely functional programming is programming with functions only...function just takes an input and produces an output and doesn't do anything else." – Runar (01:28)
- On composition:
"Composition is the superpower of functional programming." – Adam (03:18)
- On side effects:
"Instead of having a function write to disk, the function returns a little program that requests...that something might need to happen, like writing to disk." – Runar (02:05)
- On mutation and local state:
"...it's usually safe to mutate local state. So if you are in a function...and you don't actually ever look at it except in this one place...then you can consider it to be referentially transparent." – Runar (15:16)
- On exceptions:
"If you throw an exception inside of a function, it's no longer a function because it's not returning a value." – Runar (23:51)
- On constraints:
"Constraints liberate, man." – Runar (38:40)
- On abstraction and precision:
"Abstraction is really about going to a higher semantic level where we can...be absolutely precise about the things that we want to be talking about." – Runar (41:49)
Notable Segment Timestamps
- Definition of functional programming: (01:28)
- Composition and modularity: (02:37)
- Pure functions and side effects: (02:05, 07:03)
- Referential transparency explained: (08:13)
- Handling IO in FP: (10:23)
- Mutation and for-loops: (12:45, 17:03, 17:37)
- Folds and abstraction: (19:45, 20:34)
- Exceptions and error handling: (23:51, 25:27)
- Performance implications: (33:50)
- Constraints and abstraction: (38:40, 41:49)
- Teaching/learning functional programming: (45:49)
- Impact on software industry: (49:28)
Conclusion
Through this conversation, Runar Bjarnason articulates the philosophy, mechanics, and practical impact of functional programming. Adopting these design principles offers deeper modularity, easier reasoning, and powerful composition—albeit sometimes at the cost of extra constraints. By foregrounding abstraction and immutability, functional programming can make software systems more predictable, testable, and maintainable. The episode stands out both as an accessible introduction to functional programming and an invitation to dig deeper through hands-on practice.
