Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add reject (partial function) method to MonadError #2194

Merged
merged 4 commits into from
Mar 16, 2018
Merged

Add reject (partial function) method to MonadError #2194

merged 4 commits into from
Mar 16, 2018

Conversation

wogan
Copy link
Contributor

@wogan wogan commented Mar 14, 2018

Partial functions are a convenient method for expressing ensure.

In ApplicativeError handleError has another method recover which accepts PartialFunction. This is similar but for the reverse direction. If you can think of a better name than ensureP I'm open to it - perhaps reject, guard or guarantee.

@wogan
Copy link
Contributor Author

wogan commented Mar 14, 2018

Oh hang on tests still need attention. I will revisit this after I have fixed them.

@wogan wogan closed this Mar 14, 2018
@kailuowang
Copy link
Contributor

Thanks for this. The method seems useful, but I do agree that ensureP might give a false impression given the other ensure methods. reject might be a good choice.
The other issue is that, due to our commitment to maintaining binary compatibility, we can't add new methods to any public trait. So this new method might have to go to MonadErrorOps as a mere syntax extension
https://github.com/typelevel/cats/blob/master/core/src/main/scala/cats/syntax/monadError.scala

@wogan
Copy link
Contributor Author

wogan commented Mar 15, 2018

Thanks for taking a look. I've renamed it to reject and removed it from MonadError directly (leaving only the syntax extension.

Re: binary compatibility, mea cupla, I forgot adding a method to a trait isn't safe prior to Scala 2.12.

@wogan wogan reopened this Mar 15, 2018
@codecov-io
Copy link

codecov-io commented Mar 15, 2018

Codecov Report

Merging #2194 into master will increase coverage by <.01%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2194      +/-   ##
==========================================
+ Coverage   94.78%   94.78%   +<.01%     
==========================================
  Files         332      332              
  Lines        5697     5699       +2     
  Branches      214      214              
==========================================
+ Hits         5400     5402       +2     
  Misses        297      297
Impacted Files Coverage Δ
core/src/main/scala/cats/syntax/monadError.scala 100% <100%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 246b0e0...f91e792. Read the comment docs.

@@ -16,6 +16,9 @@ final class MonadErrorOps[F[_], E, A](val fa: F[A]) extends AnyVal {
def ensureOr(error: A => E)(predicate: A => Boolean)(implicit F: MonadError[F, E]): F[A] =
F.ensureOr(fa)(error)(predicate)

def reject(pf: PartialFunction[A, E])(implicit F: MonadError[F, E]): F[A] =
F.flatMap(fa)(a => if (pf.isDefinedAt(a)) F.raiseError(pf(a)) else F.pure(a))
Copy link
Contributor

@kailuowang kailuowang Mar 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is this trick that avoids calling isDefinedAt and then apply of the PartialFunction, maybe worthwhile to copy here, just a thought. Also, instead of F.pure(a) shall we just return fa?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking of doing F.flatMap(fa)(a => pf.andThen(F.raiseError[A]).applyOrElse(a, _ => fa)), though that does create a new "AndThen" object. Is avoiding the allocation important?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that might be a good balance between readability and performance.

@kailuowang kailuowang merged commit 3938d1d into typelevel:master Mar 16, 2018
@kailuowang kailuowang added this to the 1.1 milestone Mar 16, 2018
@wogan wogan changed the title Add ensureP (partial function) method to MonadError Add reject (partial function) method to MonadError Mar 16, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants