In scala, we can write the following by comprehension notation.
val result = for {
a <- Some(1)
b <- Some(2)
} yield a + b
In fsharp, we can use computation expressions.
let result =
option {
let! a = Some 1
let! b = Some 2
return a + b
}
In fp-ts, it is as follows
const result = pipe(
O.bindTo("a")(O.some(1)),
O.bind("b", () => O.some(2)),
O.map(({ a, b }) => a + b)
);
}
Can I write a similar process in rescript?
I don’t want the nesting to be too deep when chaining flatMaps.
cwstra
July 20, 2024, 4:03am
2
Rescript does not have a similar specialized syntax for these types of (i.e. monadic) computations.
There are some tools to help:
If we’re processing a singular piece of data through multiple steps, ->
can prevent the calls from nesting.
let result =
Some(5)
->Option.filter(n => n != 0)
->Option.flatMap(n => 10 / n)
->Option.map(n => n + 7)
If we need to combine a small number of values, a switch
works nicely:
let result =
switch (Some(1), Some(2)) {
| (Some(a), Some(b)) => Some(a + b)
| (_, _) => None
}
There’s not a straightforward approach to building up a scope over time, though.
3 Likes
sprkv5
July 23, 2024, 6:20pm
3
Another alternative using Array. Use this when you have a lot of values.
let a = Some(3)
let b = Some(5)
let addOptions = (acc, opt) => Some(acc->Option.getOr(0) + opt->Option.getOr(0))
let result = [a, b]->Array.reduce(None, addOptions)
2 Likes
cwstra
July 23, 2024, 6:58pm
4
On this note, while more specific to the option case, also worth knowing about Array.filterMap
and Array.keepSome
Array.filterMap([1, 3, 5, 7], n => n > 4 ? Some(n) : None)
// [5, 7]
Array.keepSome([Some("a"), None, Some("b")])
// ["a", "b"]
2 Likes