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

Introduce The Inverse Type #4345

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft

Conversation

isomarcte
Copy link
Member

@isomarcte isomarcte commented Nov 14, 2022

Introduce The Inverse Type

The type Inverse[A] is a newtype which exists to invert the Order, PartialOrder, UpperBounded and LowerBounded instances for some type A.

It's basically just Id[A] with specialized instances for ordering.

Hypothetically, we could implement all of the instances defined for Id for Inverse, however before I do that (and before I write any more docs or any tests), I wanted to see what everyone thinks about this?

Prior art: https://hackage.haskell.org/package/base-4.6.0.1/docs/Data-Ord.html#Down

Thoughts?

scala> import cats.data._
import cats.data._

scala> import scala.collection.immutable.SortedSet
import scala.collection.immutable.SortedSet

scala> SortedSet(1, 2, 3)
val res0: scala.collection.immutable.SortedSet[Int] = TreeSet(1, 2, 3)

scala> res0.map(Inverse.apply)
val res1: scala.collection.immutable.SortedSet[cats.data.Inverse[Int]] = TreeSet(3, 2, 1)

The type `Inverse[A]` is a newtype which exists to invert the `Order`, `PartialOrder`, `UpperBounded` and `LowerBounded` instances for some type `A`.

It's basically just `Id[A]` with specialized instances for ordering.

Prior art: https://hackage.haskell.org/package/base-4.6.0.1/docs/Data-Ord.html#Down
@isomarcte
Copy link
Member Author

I've also considered defining it on object Order, similar to how Data.Ord scopes Down, but given the use of NewType having it in cats.data seemed better, but I'm open to other thoughts on where it should live (assuming people want it to live anywhere).

@armanbilge
Copy link
Member

Currently we have a bunch of similar newtypes living in monoids.
https://github.com/typelevel/monoids

@isomarcte
Copy link
Member Author

🤔 hmm...I don't think Inverse[A] in and of itself implies any Semigroup or Monoid, though I agree this does have a lot of similarity to things like Max and Min in structure. Do you think I should move this over there @armanbilge? It feels a little off to me since it isn't a monoid or semigroup directly, like the other types in there, but it also feels a little off in cats-core and it isn't a collection so it doesn't feel quite right in cats-collections either. 🤷

@armanbilge
Copy link
Member

cc @typelevel/monoids

Comment on lines +49 to +50
override def hash(x: Inverse[A]): Int =
Hash[A].hash(x.value)
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like Hash[Inverse[A]].hash <==> Hash[A].hash
so what is the point of having an Inverse for Hash then?

Copy link
Member Author

Choose a reason for hiding this comment

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

There isn't if you know you're dealing with an Inverse. This is provided to solve constraints in a generic context, e.g. def foo[A: Hash] I want to be able to call that with A and Inverse[A] for all A which have a Hash.

@isomarcte isomarcte mentioned this pull request Nov 30, 2022
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.

3 participants