Well, for use by people reasonable name name is "semiring". In FriCAS
we need to do more: in common mathematical practice various details
are dismissed using phrase "it will cause no confusion to the reader"
(and frequently this phrase is used in situations which do cause
confusion). In this case important distincion is presence or absence
of neutral elements. In FriCAS Rng means a ring possibly without
a multiplicative unit while Ring means ring with multiplicative unit.
In case of semiring there are two units in question: additive one
and multiplicative one. Most general case is semiring possibly without
both additive and multiplicative unit, that is SemiRng. SemiRing
means semiring with both additive and multiplicative unit.
Join(SemiRng, AbelianMonoid) means semiring with additive unit but
possibly without multiplicative unit. Once we need to make such
fine distinctions it makes sense to have a systematic way to
create names. From this point of view Join(SemiRng, AbelianMonoid)
is quite a good name, once you grasp consepts it is clear what it
means and it is IMHO easy to remember. Alternative of having
names like SemiRngWithAdditiveUnit or
SemiRingButPossiblyWithoutMultiplicativeUnit
are clumsy and harder to remember (ypu need to remember something
which is essentially arbitreary choice).
There are also technical issues. As Ralf wrote Join is different
from named category. You seem to think that this is wrong, but in
fact this goes to very old and fundamental question about types,
namely: "When two types are equal". There are two popular answers
to this question. One answer is that each declaration creates new
type, distinct from all other types, this is typically called "name
equivalence". The second anwer is that each type is build is some
way and types build in the same way are equal. This second answer
is called "structural equivalence". Each of answers has it advanteges
and drawbacks. Arguably, name equivalence gives better support to
data abstraction: mere fact that types are build in the same way
(say both are integers at implementation level) does not mean that
the types are intended to be exchangable in any context. OTOH
in some situations we do want structural equivalence. In Modula 3
designers decided to give users both possiblities, by default
Modula 3 uses structural equivalence, but user can add a keyword
(IIRC "branded") to the definition to indicate that the type should
use name equivalence. In FriCAS types have parameters and
"type name" logically includes paramenters. So natural choice is
that types are equal when they have the same constructor and the
same parameters, where equality of parameters is recursive for
parameters being types and should use domain equality for non-type
parameters. Now, under name equivalence:
SemiRngWithAdditiveUnit : Category == Join(SemiRng, AbelianMonoid)
has different name than Join(SemiRng, AbelianMonoid), so is a different
type. Name equvalence is problematic for anonymous types. Namely
under strict interpretation each occurence of the same expression
would create a new type distinct from other types. This is of limited,
so it is natural to use structural equvalence for anonymous types. In
FriCAS trurly anonymous type are rare, but when they appear they
use structural equvalence.
Coming back to your question/problem: FriCAS algebra tries to promote
and use generic coding, that is code is supposed to run with rich
variety of types. Applicability of various methods/algorithms depends
on "features" of data, that is logical assertions and available
functions (interfaces). In FriCAS this is expressed via categories.
In order to type check Spad compiler needs to make inferences.
For Join needed inference is a general rule: Join has all properties
of its arguments. For named categories rule is a bit different:
category has properties explicitely mentioned in its definition,
which for named categories means that such category has more
properties, namely SemiRngWithAdditiveUnit above has one property more
than Join(SemiRng, AbelianMonoid), namely SemiRngWithAdditiveUnit.
So, for proper inference in Spad compiler we need in algebre code which
informs compiler about propagation for named categories. So
with named categores we need more code because we need to add various
propagation rules. For Join propagation is automatic. OTOH rules
written in code are more flexible than rule used by Join.
Anyway, using Join is natural in situations that can be handled by
it. Named categories are for for more complicated situations and
when we want to be closer to clasical mathematical nomenclature which
heavily depends on names.
--
Waldek Hebisch