fp-ts-contrib
fp-ts-contrib copied to clipboard
Do with filter (if)
🚀 Feature request
In Scala, you can do a for-comprehension with a if
:
for {
n <- Some(12)
if n < 10
m <- Some(n * 2)
} yield m
Would it be possible to do this with a Do
?
Maybe with this syntax:
Do(option)
.bind('n', some(12))
.filter(({ n }) => n < 10)
.bindL('m', ({ n }) => some(n * 2))
.return(({ m }) => m)
In Scala, the for-comprehension checks that the given Monad has a withFilter
method.
- You can't do this for an
Either
- For a
Future
, the failed value is:
But I have no idea how this could be done with aFuture(Failure(NoSuchElementException("Future.filter predicate is not satisfied")))
Task
or aTaskEither
. Maybe with aTaskOption
? - Other Monads?
This would probably work for monads that are Filterable
. Whether or not all Monads are Filterable, I do not know.
https://gcanti.github.io/fp-ts/modules/Filterable.ts.html https://gcanti.github.io/fp-ts/modules/FilterableWithIndex.ts.html
It seems a Monad
is not necessarily Filterable
. However, you could implement your own For
for things that are both Monad
and Filterable
. It could use ´Do´ for the operations that do not require for the type to be Filterable
.
I made an experimental implementation of For notation. However, I can not figure out how to reuse code from the DoClass so I had to use copy/paste to make it work. Other than that it seems to work. See https://github.com/cyberixae/fp-ts-contrib/commits/implement_for_notation
Oh wow! Nice job!
I was thinking about the method's name: wouldn't this be closer to the usual conventions of fp-ts
:
For(option)
.bind('n', some(12))
.filter(2 > 3)
.filterL(({ n }) => n < 10)
.return(({ n }) => n)
But I don't see cases where filter isn't lazy.
The L
stands for lambda. I think it would be nice to have the constants have a suffix instead of the lambdas since the constant versions are more of a special case. I don't think the L suffix naming is from fp-ts
. I'm not sure if it makes sense to add the For
notation to fp-ts-contrib
. Maybe you could fork it and create your own npm package that implements the for notation. You could then make it more appealing to people with Scala background. Just an idea though. Don't feel obliged to do so.
I always thought that in fp-ts
the L
stands for lazy. In v1 of fp-ts
, for instance for Option.getOrElse
, there used to be both getOrElse
et getOrElseL
signatures.
https://github.com/gcanti/fp-ts/blob/1.x/docs/modules/Option.ts.md#getorelse-method-1
I have no problem with not adding For
to fp-ts-contrib
. This was just a suggestion and I managed to make my code work without it :)
Perhaps it was used for lazy in fp-ts
however the Do
notation was developed separately. See https://paulgray.net/do-syntax-in-typescript/#do-l-bind-l-sequence-sl-let-l-variants