Chain functions using Option type - Functional Programming
24 July 2022［updated］•
5 min read• Functional programming
The most interesting property of Functional Programming is composition. The
Option type allows composing small functions to form a bigger function. Since every function is pure, we can test every single function in isolation.
If all the basic functions are correct, we can be (almost) sure that a bigger and more complex function composed from these building blocks is also correct!
Today you will learn four methods used to compose
alt: Provides an alternative
Optionin case the current one is
andThen: If the current
Optioncontains a value (
Some) return a new given
flatMap: Extract the value inside the
Optionif it is present and return a new
Option, otherwise return
getOrElse: Extract the value if present, or provided a fallback value if it is not present.
I highly encourage you to read the previous article in the series. Many of the basic concepts have been explained in the previous article, so you may have trouble understand this post if you do not read the previous one.
The example of this article is all about shopping:
You want to go shopping. Your first option is going to the Shopping Center. Nonetheless, if the Shopping Center is closed, you will go to the Local Market, which is always open.
You want to buy exactly one Banana (🍌), one Apple (🍎), and one Pear (🍐). If any one of these fruits is missing, you will leave empty handed and not buy anything.
We will model these instructions using Functional Programming with the
Your first idea is to go to the Shopping Center. You define a function for doing this:
Option<Unit> goToShoppingCenter() => getRandomOption(unit);
This function returns the given
valuerandomly wrapped in an
Some(value)half the times, and
None()the other half.
The function returns an
Option, since 50% of the times the Shopping Center is closed!
You also define an alternative function to go to the Local Market:
Option<Unit> goToLocalMarket() => some(unit);
This function always returns a
Some, since the Local Market is always open!
Now you want to combine these two functions. You try to go to the Shopping Center. If it is closed, you will go to the Local Market instead:
goToShoppingCenter().alt( goToLocalMarket, );
We use the
alt function. If
alt will just return this
alt will return the result of calling
Regardless of which market we choose, we want to start buying some fruits!
We don't really care about the
Unit that the two previous functions return. We are just going to ignore it and start buying:
goToShoppingCenter().alt( goToLocalMarket, ).andThen(() => /** Let's buy! */);
andThen throws away the result of the previous
Option if it is a
Some and just calls the given function. If the previous
andThen will also return
Now you are inside the market and ready to buy. You want all the fruit on your shopping list. If any of the fruit is not available, you will just leave and not buy anything.
We define three functions that give us our fruits (only 50% of the time):
Option<String> buyBanana() => getRandomOption('🍌'); Option<String> buyApple() => getRandomOption('🍎'); Option<String> buyPear() => getRandomOption('🍐');
You are going to check the availability of all these three fruits one by one. If, at any step in the process, you don't find the fruit you were looking for, you will just leave all the other fruits taken since then and leave:
goToShoppingCenter() .alt( goToLocalMarket, ) .andThen( () => buyBanana().flatMap( (banana) => buyApple().flatMap( (apple) => buyPear().flatMap( (pear) => Option.of('Shopping: $banana, $apple, $pear'), ), ), ), );
flatMap to chain these functions.
flatMap will call the given function only when the
Some. If any of the
Option in the chain is
None, then the whole chain will return
Finally, once you are back home you check what you bought. If you did not find your fruits, you will just notify your family. Otherwise you will show the result of your expedition:
// Combine all the instructions and go shopping! 🛒 String goShopping() => goToShoppingCenter() .alt( goToLocalMarket, ) .andThen( () => buyBanana().flatMap( (banana) => buyApple().flatMap( (apple) => buyPear().flatMap( (pear) => Option.of('Shopping: $banana, $apple, $pear'), ), ), ), ) .getOrElse( () => 'I did not find 🍌 or 🍎 or 🍐, so I did not buy anything 🤷♂️', );
getOrElse returns the value inside the
Option if the
Some, Otherwise, it returns the given value in the provided function.
We record the results of our visit to the market for 100 days, and this is the result:
Sometimes you find all the fruits and you buy them, other times you just leave empty-handed.
- How to use the methods
flatMapto chain functions returning
- How to use
getOrElseto extract the value from an
- How to model a Functional Programming application using
You can find the complete example in the fpdart repository:
Do you like these short articles on Functional Programming? Let me know on Twitter at @SandroMaglione. Follow me for daily updates on Functional Programming, dart, Flutter, mobile, and web development. If you are interested in more tips and guides about these topics, subscribe to my newsletter here below 👇