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 PartialFunction instance for Profunctor typeclass #3392

Conversation

gagandeepkalra
Copy link
Contributor

@gagandeepkalra gagandeepkalra commented Apr 13, 2020

resolves #3386

*/
override def dimap[A, B, C, D](fab: PartialFunction[A, B])(f: C => A)(g: B => D): PartialFunction[C, D] =
new PartialFunction[C, D] {
override def isDefinedAt(c: C): Boolean = fab.isDefinedAt(f(c))
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 don't think if there's any way out of running f twice

@codecov-io
Copy link

Codecov Report

Merging #3392 into master will decrease coverage by 0.22%.
The diff coverage is 75.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #3392      +/-   ##
==========================================
- Coverage   92.70%   92.48%   -0.23%     
==========================================
  Files         379      379              
  Lines        7981     7960      -21     
  Branches      230      226       -4     
==========================================
- Hits         7399     7362      -37     
- Misses        582      598      +16     
Flag Coverage Δ
#scala_version_212 ?
#scala_version_213 92.48% <75.00%> (-0.01%) ⬇️
Impacted Files Coverage Δ
...rc/main/scala/cats/instances/partialFunction.scala 75.00% <75.00%> (ø)
core/src/main/scala/cats/data/OneAnd.scala 79.10% <0.00%> (-16.49%) ⬇️
core/src/main/scala/cats/Reducible.scala 97.22% <0.00%> (-2.78%) ⬇️
core/src/main/scala/cats/syntax/either.scala 81.61% <0.00%> (-1.72%) ⬇️
...rc/main/scala/cats/laws/discipline/arbitrary.scala 98.29% <0.00%> (-0.86%) ⬇️
core/src/main/scala/cats/Show.scala 67.56% <0.00%> (-0.86%) ⬇️
core/src/main/scala/cats/instances/try.scala 86.44% <0.00%> (-0.45%) ⬇️
core/src/main/scala/cats/data/Tuple2K.scala 91.30% <0.00%> (-0.19%) ⬇️
.../src/main/scala/cats/laws/discipline/MiniInt.scala 97.22% <0.00%> (-0.08%) ⬇️
core/src/main/scala/cats/data/NonEmptyChain.scala 92.92% <0.00%> (-0.08%) ⬇️
... and 11 more

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 def9a6f...d2edf3f. Read the comment docs.

LukaJCB
LukaJCB previously approved these changes Apr 13, 2020
Copy link
Member

@LukaJCB LukaJCB left a comment

Choose a reason for hiding this comment

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

Thanks for this! :)

@LukaJCB
Copy link
Member

LukaJCB commented Apr 13, 2020

I wonder if we could add instances for the other parts of the arrow hierarchy. Seems like we could implement pretty much everything, no?

@gagandeepkalra
Copy link
Contributor Author

@LukaJCB I updated the same PR instead, is it okay?

@gagandeepkalra gagandeepkalra requested a review from LukaJCB April 16, 2020 10:06
LukaJCB
LukaJCB previously approved these changes Jun 2, 2020
Copy link
Member

@LukaJCB LukaJCB left a comment

Choose a reason for hiding this comment

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

Hey @gagandeepkalra sorry for keeping you waiting for so long, this looks amazing, thanks! Do you have time to rebase with master? :)

@gagandeepkalra gagandeepkalra force-pushed the profunctor/addPartialFunctionInstance branch from ff84eea to 6af528d Compare June 3, 2020 15:57
@codecov-commenter
Copy link

codecov-commenter commented Jun 3, 2020

Codecov Report

Merging #3392 into master will increase coverage by 0.42%.
The diff coverage is 94.73%.

@@            Coverage Diff             @@
##           master    #3392      +/-   ##
==========================================
+ Coverage   91.63%   92.05%   +0.42%     
==========================================
  Files         382      383       +1     
  Lines        8304     8347      +43     
  Branches      232      210      -22     
==========================================
+ Hits         7609     7684      +75     
+ Misses        695      663      -32     

@gagandeepkalra
Copy link
Contributor Author

Thank you @LukaJCB @barambani for the review, learnt something new today.

@barambani
Copy link
Contributor

Thank you.

learnt something new today.

same here.

@gagandeepkalra gagandeepkalra requested a review from LukaJCB June 5, 2020 11:12
Copy link
Member

@LukaJCB LukaJCB left a comment

Choose a reason for hiding this comment

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

Hey, thanks! This looks great, but I wonder why you only placed it in the companion objects of Profunctor and Compose, maybe I'm missing something?

@barambani
Copy link
Contributor

@LukaJCB I suggested it to align to the approach taken here #3043

@LukaJCB
Copy link
Member

LukaJCB commented Jun 5, 2020

Ah of course! Sorry I misremembered a detail of the whole thing

LukaJCB
LukaJCB previously approved these changes Jun 5, 2020
Copy link
Contributor

@travisbrown travisbrown left a comment

Choose a reason for hiding this comment

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

👍 to the concept—I'm not sure why we hadn't done this before. I do have a couple of comments / questions about details.

@@ -41,9 +41,12 @@ import scala.annotation.implicitNotFound
}

object Compose {
implicit def catsInstancesForFunction1: ArrowChoice[Function1] with CommutativeArrow[Function1] =
implicit val catsInstancesForFunction1: ArrowChoice[Function1] with CommutativeArrow[Function1] =
Copy link
Contributor

Choose a reason for hiding this comment

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

It's not really a big deal, but there is a reason for these to be methods instead of vals: they're already instantiated as vals in the instances objects, so using def here won't result in new instantiations, but using a val does result in a little extra overhead and indirection, since it generates both an accessor method and a field.

In general this is unlikely to matter much, but because there are a lot of these, we've had a policy of def instead of val.

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 see, that's a nice way of saving up on a reference; apologies for oversight

@@ -10,6 +10,7 @@ abstract class AllInstancesBinCompat
with AllInstancesBinCompat4
with AllInstancesBinCompat5
with AllInstancesBinCompat6
with AllInstancesBinCompat7
Copy link
Contributor

@travisbrown travisbrown Jun 11, 2020

Choose a reason for hiding this comment

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

We shouldn't need any new BinCompat traits now that we've dropped 2.11. You should be able to add PartialFunctionInstances directly to AllInstances, I believe?

Copy link
Contributor Author

@gagandeepkalra gagandeepkalra Jun 11, 2020

Choose a reason for hiding this comment

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

I'm not sure, getting this error when adding to AllInstances; I don't see anything obvious, might need some help

[error] Cats core: Failed binary compatibility check against org.typelevel:cats-core_2.12:1.0.1! Found 2 potential problems (filtered 481)
[error] * abstract synthetic method cats$instances$PartialFunctionInstances$setter$catsStdInstancesForPartialFunction_=(cats.arrow.ArrowChoice)Unit in interface cats.instances.PartialFunctionInstances is inherited by class AllInstances in current version.
[error] filter with: ProblemFilters.excludeInheritedNewAbstractMethodProblem
[error] * abstract method catsStdInstancesForPartialFunction()cats.arrow.ArrowChoice in interface cats.instances.PartialFunctionInstances is inherited by class AllInstances in current version.
[error] filter with: ProblemFilters.excludeInheritedNewAbstractMethodProblem

Copy link
Contributor

Choose a reason for hiding this comment

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

@gagandeepkalra Hmm, thanks, I'll take a look now.

@travisbrown
Copy link
Contributor

Oh, right. The issue is that adding a val to a trait still breaks bincompat even on 2.12+, because of synthetic methods. We've had to work around this in a couple of other places—let me find a link…

@travisbrown
Copy link
Contributor

Here's some explanation of the issue: #2789 (comment)

I think that something like this should work:

trait PartialFunctionInstances {
  def catsStdInstancesForPartialFunction: ArrowChoice[PartialFunction] with CommutativeArrow[PartialFunction] =
    PartialFunctionInstances.instance
}

private object PartialFunctionInstances {
  private val instance: ArrowChoice[PartialFunction] with CommutativeArrow[PartialFunction] =
    new ArrowChoice[PartialFunction] with CommutativeArrow[PartialFunction] {
      // ...

I'd be happy to merge this PR as-is, and I can fix this particular part in a follow-up, if you'd prefer?

@travisbrown travisbrown self-requested a review June 12, 2020 08:40
travisbrown
travisbrown previously approved these changes Jun 12, 2020
Copy link
Contributor

@travisbrown travisbrown left a comment

Choose a reason for hiding this comment

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

There's one remaining issue, but I think it could be handled in a follow-up PR, so I'm approving this now. Thanks again @gagandeepkalra!

…improved doctests with less imports now needed
@gagandeepkalra
Copy link
Contributor Author

@travisbrown thank you, summarising-

I understand why adding a def to trait won't break bc given we have method defaults in java 8 interface, while though val would still require each class this trait is mixed in with, recompilation.

Meanwhile I had another doc-test import related improvement, so have pushed both together.

Copy link
Contributor

@travisbrown travisbrown left a comment

Choose a reason for hiding this comment

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

@gagandeepkalra Thanks, that looks good to me! I don't it necessarily needs a second re-review, but I'll leave it for right now for @LukaJCB to take a look if he wants.

I don't remember the details about why adding a val to a trait breaks bincompat in 2.12, but right, it has something to default methods (and the implementation of initialization using static forwarder methods on the companion object).

@travisbrown
Copy link
Contributor

Going ahead and merging this since it had an earlier second 👍.

@travisbrown travisbrown merged commit 97468fa into typelevel:master Jun 16, 2020
@travisbrown travisbrown added this to the 2.2.0-M3 milestone Jun 17, 2020
@gagandeepkalra gagandeepkalra deleted the profunctor/addPartialFunctionInstance branch June 18, 2020 01:30
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.

Profunctor[PartialFunction]
6 participants