Add Boolean.otherwise and AnyF.withFilter for MonadError for-comprehension guards#609
Add Boolean.otherwise and AnyF.withFilter for MonadError for-comprehension guards#609torbenfreise wants to merge 2 commits intotypelevel:mainfrom
Conversation
Add otherwise to boolean
|
Thanks for your contribution @torbenfreise I have one request: the two changes work together to enable this cute syntax in for-expr, so please include a unit test that uses them in for-expression mode. That proves that this |
7e9d24b to
831b378
Compare
831b378 to
f5b5c68
Compare
|
@benhutchison thanks for your review, I added the test case. While writing this test case, I also noticed that scalafmt rewrites it as if (age >= 18).otherwise("Age must be at least 18")which makes the syntax a bit less cute unfortunately. |
|
Honestly, I feel concerned about both of the proposed extensions:
|
|
I find @satorg second point quite compelling. withFilter is broadly supposed to narrow a result using a predicate, but here we have an effectful call def withFilter[E](f: A => F[Unit])(implicit F: MonadError[F, E]): F[A] My bad for not raising this earlier. |
|
Thanks for the feedback, The compiler also gives a very unhelpful error: found : Boolean
required: Either[Throwable,Unit]I also agree that it is unintuitive that a predicate should be an effect with error / unit replacing false / true as you said @benhutchison. I guess for this to be done properly, it would require a change to how Scala desugars for comprehensions, so that for {
...
if pred else zero // desugars to withFilterOrElse(pred, zero)
}
for {
a <- 2.asRight[Throwable] if a % 2 == 0
// fails to compile with the normal 'cannot resolve symbol withFilter' error
}filterOrElse already exists on Either, so |
|
I created a SIP for it here in case you are interested. |
Adds two methods:
otherwise on BooleanOps - raises an error in any ApplicativeError context if the boolean is false.
withFilter on AnyFOps - enables filtering on MonadError types like Either.
These enable the use of typed 'if' guards in for-comprehensions over MonadError types, which is the main motivator behind this PR. For instance, instead of writing:
We can write: