Example 1: Ignoring the First Value with O.andThen
Concept
The O.andThen
function allows you to execute a sequence of two Option
s, where the result is determined solely by the second Option
. This is useful when the first Option
serves a purpose, but its value isn't needed in subsequent operations.
Code
function sequencing_ex01() {
const some1 = O.some(1); // Create an Option containing the value 1
const some2 = O.some(2); // Create an Option containing the value 2
const none = O.none(); // Create an Option representing no value
console.log(pipe(some1, O.andThen(some2))); // Output: Some(2) (ignores 1 and returns 2)
console.log(pipe(none, O.andThen(some2))); // Output: None (since the first Option is None)
}
Explanation
-
pipe(some1, O.andThen(some2))
: Here,some1
holds the value1
, but the operation ignores it and returnssome2
, which holds2
. -
pipe(none, O.andThen(some2))
: Since the firstOption
isNone
, the operation short-circuits and returnsNone
.
This sequencing operation is particularly useful when you want to chain operations but are only interested in the outcome of the second operation.
Example 2: Flattening Nested Options with O.flatten
Concept
The O.flatten
function is designed to handle nested Option
s by removing one level of nesting. This is useful when your operations result in an Option
of Option
, and you need to simplify it into a single Option
.
Code
function sequencing_ex02() {
const nestedSome = O.some(O.some(1)); // Create a nested Option containing the value 1
const nestedNone = O.some(O.none()); // Create a nested Option representing no value
const none = O.none(); // Create an Option representing no value
console.log(pipe(nestedSome, O.flatten)); // Output: Some(1) (flattens the nested Option)
console.log(pipe(nestedNone, O.flatten)); // Output: None (flattens to None)
console.log(pipe(none, O.flatten)); // Output: None (since the outer Option is None)
}
Explanation
-
pipe(nestedSome, O.flatten)
: This flattens theOption
ofOption
into a singleOption
, resulting inSome(1)
. -
pipe(nestedNone, O.flatten)
: The innerOption
isNone
, so flattening results inNone
. -
pipe(none, O.flatten)
: If the outerOption
isNone
, flattening has no effect, andNone
is returned.
Flattening is essential when dealing with functions that may return nested Option
s, allowing you to streamline the result into a single Option
value.
Example 3: Composing Option-returning Functions with O.composeK
Concept
The O.composeK
function allows you to compose two functions that return an Option
, creating a pipeline where the output of the first function is fed into the second. This is particularly useful for chaining operations that may fail and result in None
.
Code
function sequencing_ex03() {
const parseNumber = (s: string): O.Option<number> => {
const n = parseInt(s, 10);
return isNaN(n) ? O.none() : O.some(n);
};
const doubleIfPositive = (n: number): O.Option<number> =>
n > 0 ? O.some(n * 2) : O.none();
const parseAndDouble = pipe(parseNumber, O.composeK(doubleIfPositive));
console.log(parseAndDouble('42')); // Output: Some(84) (parses and doubles the number)
console.log(parseAndDouble('-1')); // Output: None (since -1 is not positive)
console.log(parseAndDouble('abc')); // Output: None (since 'abc' is not a number)
}
Explanation
-
parseAndDouble('42')
: The string'42'
is successfully parsed to a number, and since it’s positive, it’s doubled, resulting inSome(84)
. -
parseAndDouble('-1')
: The string'-1'
is parsed, but since it’s negative, the function returnsNone
. -
parseAndDouble('abc')
: The string'abc'
cannot be parsed as a number, so the function returnsNone
.
Composing Option
-returning functions allows you to create complex chains of operations while safely handling cases where any step in the chain may fail.
Conclusion
These examples showcase the versatility and power of the Option
type in Effect-TS for handling sequences of operations. Whether you're ignoring values with O.andThen
, flattening nested Option
s with O.flatten
, or composing operations with O.composeK
, these patterns enable you to manage optional values more effectively in a functional programming context. By leveraging these techniques, you can write more robust and concise code, ensuring that operations gracefully handle the absence of values while maintaining clear and readable logic.
Top comments (0)