What is the binary compatibility story of algebra anyway?

I think algebra should follow cats typelevel/cats#1233 WRT binary compat, its similarly fundamental. It can still break binary compat when needed, but such changes should be deliberate and considered, not accidental, and signalled via version numbers.

Should every dependency in a project be tied to a specific algebra release?

Ideally, no, the tying mainly happens when there are compat breaks. At minimum, libs differing on the patch version of algebra they depend upon should never be a problem.

Been looking into Algebra syntax some more. There's a problem.

What it amounts to, in my mental model, is a refactor of Spire's syntax, moving the syntax near to (ie same project as) their related typeclasses.

The problem is that those typeclasses are spread across Spire, Algebra and Cats Kernel (eg PartialOrder)

But the syntax for cats kernel isn't in Kernel, its in Cats Core (eg PartialOrder syntax). And algebra doesnt depend upon cats core, so it cannot see or use the kernel syntax

When you "take stock" of what syntax in Spire could be moved to Algebra, it becomes evident that a huge piece of it comes from kernel and not from Algebra.

To the point that there's little point trying to add Algebra syntax without first moving Kernel syntax somewhere that Algebra could reuse it.

Doing that amounts to a migration within cats, adding a syntax package to kernel and adding redirects from cats core.

If there's a takeaway lesson from this, its: *if you care about syntax, keep it with the relevant typeclasses*

@benhutchison, I respectfully disagree. Algebra is all about compatibility of typeclasses, so it should be as small as possible. The compatibility guarantees proposed for *and* minor versions.

`cats-kernel`

are very good in that sense: binary compatibility across patch
This is especially relevant when dealing with numerical/mathematical code, where you often find libraries that have not been maintained for years.

(Because it was written for a PhD thesis, and the author left academia long ago, for example)

But the binary compatibility of syntax is actually a different story: because everything happens using macros, there are no runtime dependencies for those JARs. Having a syntax module in algebra is a very good idea; let's put it in a different module, and if possible we tag the corresponding JAR as compile-time only (if there is such a possibility). Then we never need to worry about binary compatibility.

Algebra is going to be the root of many diamonds in the JAR hell.

To give one example: I disagree with the

`Group[G].empty`

syntax used to describe the identity element, instead of the mathematical `Group[G].id`

. But I'm not going to change the underlying `cats.kernel`

typeclass. I'm going to add a short enrichment class to provide `Group[G].id`

and `Group[G].isId`

, and I don't need to break the binary compatibility -- in a sense I define partly my own syntax.
For the source/binary compatibility story, a good example is the package

`ARep`

written for GAP version 3. Because it's difficult to port `ARep`

to GAP version 4, several research groups choose to maintain the whole GAP 3 computer algebra system (dating from 1997!) and provide builds for recent Linux distributions.
Algebra is all about compatibility of typeclasses, so it should be as small as possible.

@denisrosset We're in alignment that typeclass compat is important, I dont think Im proposing anything that contradicts that. But that's not all algebra could be about. It could, *should* IMO, also be useful in its own right.

And every useful typeclass lib in Scala ends up needing syntax enrichment. So if you leave syntax out of either Algebra or Cats Kernel we in effect say, "these libraries must be wrapped within another to be useful".

My position is that we should recognize, based on 10s of examples now, that useful Scala typeclass libs consist of 3 parts: typeclasses themselves, common instances, and syntax to enable infix and postfix operators. Keep the parts together! I see a tendency to treat syntax as a second class citizen, but in practice all the usage I see in the wild assumes syntax is enabled.

I didnt see the relevance of your `Group[G].empty`

example to syntax, since the `empty`

operator isn't provided via syntax but is on the typeclass?

To be clear, when Ive said "syntax" above I specifically refer to enrichment via implicit conversion to enable infix and postfix operators defined on the datatypes of the typeclass. Not "surface syntax" more generally.