Closed tixxit closed 7 years ago
Sounds like we need a Bijection. :) We added something like this to Bijection actually: https://github.com/twitter/bijection/pull/183/files which let's you generalize this imap idea.
Also, it algebird we added bijected algebras: https://github.com/twitter/algebird/blob/develop/algebird-bijection/src/main/scala/com/twitter/algebird/bijection/AlgebirdBijections.scala#L31
Here, Eq.on is the same as contramap. As is Order.on.
About imap, see #108. That one, which I think should probably rarely be used (at Twitter, bijected algebras are pretty rare actually. One benefit of the bijected algebra is that you can leverage combineAll to not apply the bijection too much, but the naive approach of applying both functions on each combine to combine a big list is costly).
I'd probably not add imap, and instead make a class similar to BijectedRing to handle this.
In Cats I originally had a bijection type but realized I didn't want to step on twitter/bijection's toes, so we removed it. I agree that it's a lot cleaner.
I think the "bijected algebra" (or "mapped algebra") approach makes a lot of sense for the reasons you mention. I could imagine a similar argument being used in favor of putting concrete sorting implementations on Order
so it could be more efficient in these cases as well, but I'm not sure that would be the right decision, since there are so many other methods you might want too (sorting, selecting, searching, etc).
It could also be
contramap[A, B](ra: Ring[A])(f: Iso[B, A]): Ring[B]
but I guess folks don't want to pull in a lens library.
EDIT: I corrected Lens
to Iso
.
@johnynek Ah - that looks delightful. If we had these methods existing on the type classes already, then it would make the implementation of a TypeclassBijection
easier, right? The bijection style looks nice, but it doesn't preclude us from having some combinators on the type classes to start? As you noted, they already exist for Eq
and Order
.
For types like
Ring
, we should include animap(f: A => B, g: B => A): Ring[B]
method for transforming the type class. This also includecontramap(f: B => A)
on type classes likeEq
andOrder
.