Learning F# - The Thunderdome Principle for Functions
December 26, 2015Back in 2008, Jeremy Miller introduced the Thunderdome Principle, a technique he used for building maintainable ASP.NET MVC applications which later led to the FubuMVC open-source project. The basic premise of the Thunderdome Principle is to have all controller methods take in one ViewModel object (or none in some cases), and also return a single ViewModel object. One object enters, one object leaves!
What I like about F# is that the language designers took a similar approach when they implemented functions. In F#, every function accepts exactly one input and returns exactly one output. This is a different approach compared to C# where there is a distinction between functions that return values and those that don’t return values. This choice made by the designers of the C# programming language even bleeds into the .NET framework itself by incorporating a Func delegate and an Action delegate.
But F# is having none of that! Let’s have a look at the following function and it’s corresponding type annotation:
let multiply x y = x * y
> val multiply : x:int -> y:int -> int
At first glance this looks like a function that takes two arguments and returns a result. But the type annotation tells us a different story. Here multiply is bound to a function that takes an integer argument “x” and returns a function. This second function takes another integer argument “y” and returns an integer.
This approach of “one input value, one output value” has several benefits. One example is that the F# compiler can assume that the last expression in a function is also the return value. Therefore we didn’t need to use the return keyword in our example.
But another major benefit is partial application. Let’s have a look at the following code:
let multiplyByTen = multiply 10
> val multiplyByTen : (int -> int)
let result = multiplyByTen 5
> val result : int = 50
Here the F# compiler evaluated the call to the multiply function as far as possible, and simply bound multiplyByTen to the function for which it didn’t receive the parameter value. So partial application only works for function arguments from left to right.
That’s all fine, but what about functions that don’t take any arguments or don’t have a value to return? This is where the unit type comes in.
let logSomethingUseful = printfn "Hi there"
> val logSomethingUseful : unit = ()
Here we have a function with no arguments and no return value. However, behind the scenes, unit is passed to the function whereas unit is also returned by the function.
In my humble opinion, this whole “one input value, one output value” approach is by far a more cleaner model that is easier to understand. On several occasions while developing C# code, I wished that the .NET framework provided me with only Func delegates and a first-class void type. F# grants me this wish.
Until next time.
If you and your team want to learn more about how to write maintainable unit tests and get the most out of TDD practices, make sure to have look at our trainings and workshops or check out the books section. Feel free to reach out at info. @ principal-it .be
Jan Van Ryswyck
Thank you for visiting my blog. I’m a professional software developer since Y2K. A blogger since Y2K+5. Provider of training and coaching in XP practices. Curator of the Awesome Talks list. Past organizer of the European Virtual ALT.NET meetings. Thinking and learning about all kinds of technologies since forever.
Comments
Writing Maintainable
Unit Tests
Watch The Videos
Latest articles
-
Contract Tests - Parameterised Test Cases
June 28, 2023
-
Contract Tests - Abstract Test Cases
April 12, 2023
-
Contract Tests
February 1, 2023
-
The Testing Quadrant
June 15, 2022
-
Tales Of TDD: The Big Refactoring
February 2, 2022
Tags
- .NET
- ALT.NET
- ASP.NET
- Agile
- Announcement
- Architecture
- Behavior-Driven Development
- C++
- CQRS
- Clojure
- CoffeeScript
- Community
- Concurrent Programming
- Conferences
- Continuous Integration
- Core Skills
- CouchDB
- Database
- Design Patterns
- Domain-Driven Design
- Event Sourcing
- F#
- Fluent Interfaces
- Functional Programming
- Hacking
- Humor
- Java
- JavaScript
- Linux
- Microsoft
- NHibernate
- NoSQL
- Node.js
- Object-Relational Mapping
- Open Source
- Reading
- Ruby
- Software Design
- SourceControl
- Test-Driven Development
- Testing
- Tools
- Visual Studio
- Web
- Windows
Disclaimer
The opinions expressed on this blog are my own personal opinions. These do NOT represent anyone else’s view on the world in any way whatsoever.
About
Thank you for visiting my website. I’m a professional software developer since Y2K. A blogger since Y2K+5. Author of Writing Maintainable Unit Tests. Provider of training and coaching in XP practices. Curator of the Awesome Talks list. Thinking and learning about all kinds of technologies since forever.
Latest articles
Contract Tests - Parameterised Test Cases
Contract Tests - Abstract Test Cases
Contract Tests
The Testing Quadrant
Contact information
(+32) 496 38 00 82
info @ principal-it .be