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 Invariant instances for Numeric and Integral #3773

Merged
merged 11 commits into from
Feb 9, 2021

Conversation

tmccarthy
Copy link
Contributor

Fixes #3220.

This PR continues the work done in #3222 by @kubukoz. My additional work is:

  • Add instances on the Invariant companion
  • Fix binary compatibility issues with AllInstances
  • Support 2.12 and 2.13+ by handling the parseString method that was added to Numeric in 2.13
  • Add Invariant[Integral]

Note that I haven't added Invariant[Fractional] because the laws testing looks to be a bit messy. I might think a bit more on how to test such an instance and add it in a separate PR.

def toLong(x: B): Long = fa.toLong(g(x))
def toFloat(x: B): Float = fa.toFloat(g(x))
def toDouble(x: B): Double = fa.toDouble(g(x))
def parseString(str: String): Option[B] = fa.parseString(str).map(f)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This differs from the 2.12 implementation because parseString was added in 2.13.

Comment on lines -240 to -244
Eq[Band[Set[Boolean]]]
cats.laws.discipline.ExhaustiveCheck[Set[Boolean]]
Eq[(Set[Boolean], Boolean)]
Eq[(Set[Boolean], Set[Boolean] => (Set[Boolean], Boolean))]
Eq[CommutativeSemigroup[Set[Boolean]]]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

There was a question about these lines in the previous PR. I've removed them but happy to revert if they are necessary.

Copy link
Contributor

Choose a reason for hiding this comment

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

They might be compilation tests, no?

Copy link
Contributor

Choose a reason for hiding this comment

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

On second thought, they probably don't belong there at all. So let's keep them removed.

Comment on lines 32 to 38
// These allow us to capture the cases where operations on Numeric throw (eg when causing an overflow). These are
// represented by `None` and allow us to compare two Numeric instances, verifying that when one throws, the other
// also throws.
def makeUnaryFnSafe[X, R](f: X => R): X => Option[R] =
x => Either.catchOnly[IllegalArgumentException](f(x)).toOption
def makeBinaryFnSafe[X, Y, R](f: (X, Y) => R): (X, Y) => Option[R] =
(x, y) => Either.catchOnly[IllegalArgumentException](f(x, y)).toOption
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note that here and in a couple of other places, I've had to find a way of reconciling the unsafe nature of the methods on Numeric with defining an Eq.

My approach has been to require that for two Numeric instances to be equal, when one throws the other throws. Lifting the values into Option and using None to represent cases that throw erases the difference between different types of thrown exceptions. I've decided that this is okay given the alternative would be a dirty Eq for ArithmaticException and IllegalArgumentException.

Happy to change this approach to something else.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually I think this is unnecessary except in the fromInt case. I will rework it...

@tmccarthy
Copy link
Contributor Author

The test failure looks to be unrelated to my changes.

@tmccarthy tmccarthy marked this pull request as ready for review February 7, 2021 09:20
@larsrh
Copy link
Contributor

larsrh commented Feb 7, 2021

The test failure looks to be unrelated to my changes.

Probably a flaky test.

@larsrh larsrh added this to the 2.4 milestone Feb 9, 2021
@larsrh larsrh merged commit 696bbab into typelevel:master Feb 9, 2021
@tmccarthy tmccarthy mentioned this pull request Oct 31, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add Invariant[Numeric]
3 participants