#10963: More functorial constructions
-------------------------------------+-------------------------------------
Reporter: nthiery | Owner: stumpc5
Type: enhancement | Status: needs_info
Priority: major | Milestone: sage-6.2
Component: categories | Resolution:
Keywords: days54 | Merged in:
Authors: Nicolas M. Thiéry | Reviewers: Simon King, Frédéric
Report Upstream: N/A | Chapoton
Branch: | Work issues:
public/ticket/10963-doc- | Commit:
distributive | c718f218fbc726bf3cf7f4c3f20638c9b0c7eea7
Dependencies: #11224, #8327, | Stopgaps:
#10193, #12895, #14516, #14722, |
#13589, #14471, #15069, #15094, |
#11688, #13394, #15150, #15506 |
-------------------------------------+-------------------------------------
Comment (by vbraun):
Replying to [comment:500 nthiery]:
> > {{{#!python
> > class Test2(Category):
> > class FiniteCommutative2(axioms.Finite.Category,
axioms.Commutative.Category):
> > pass
> > }}}
I decided on the special `InnerCategory` class as a marker for inner
categories because it is unambiguous both
* for Python: maybe you want an unrelated category nested inside your
class without having it mangled by the metaclass,
* for authors: even if the enclosing class is off-screen you know that you
are declaring a subcategory.
Also, it simplifies the chicken-and-egg problem for the metaclass
constructing the `Category` base. Technically, the `InnerCategory` is not
a category since the usual Python rules would run the metaclass for the
inner class first, whereas we want to assemble the outer class first.
> {{{_base_category_class_}}} since it's a Sage special attribute, not a
> Python one; but that's just a detail.
I thought about that and decided on `__double__` underscores for
attributes set by the metaclass. It makes it clear that they aren't quite
your run-of-the-mill Sage hidden attributes, but that special rules apply.
And it should be clear enough from the name that `__base_category_class__`
is not an ordinary Python attribute.
> > One thing that I think is tricky is to derive rules from implications
A => B => C => A, especially if `all_super_categories` is actually missing
some super categories.
>
> Ok. We agree that the current infrastructure has no problem with that,
> right?
I don't think so, it depends on exactly which super categories you pick. I
certainly agree that it can work if your declared super categories are
sufficiently close to the actual immediate super categories, but it seems
difficult to a) get right and b) diagnose what goes wrong otherwise.
> - The main point is that it removes the current limitation that we can
> add only a single axiom at a time, right? How many spots in the
> current category code will be improved by this?
The main point is that it separates class names from program flow. You can
name your category classes any way you want, their relation has to be
specified in code. It seemed natural to not restrict to a single axiom,
but thats just a by-product.
> - Will it allow for completely getting rid of the couple remaining
> "placeholder categories", both statically and dynamically?
> - Is it going to reuse the current join implementation, for example by
> delegating the work to it by building the required arborescence
> behind the scene? Or will the manager replace this piece too? If
> it's not using an arborescence of some kind, what kind of complexity
> can we roughly expect to have?
I don't want to change the existing join implementation, so you need to
dynamically generate category + single axiom if it is not defined
statically. This is the `CategoryAxiomModel.construct_with_one_axiom`
method. Which category classes to generate dynamically is the one place
that involves choices, which is very clear in the implementation.
> - Will the proposal make for a cleaner implementation of axioms like
> Distributive?
> {{{
> sage: (CommutativeAdditiveGroups() & Monoids()).Distributive()
> Category of rings
> }}}
Essentially I'm just forcing all category construction to go through a
single factory object, which then can implement arbitrarily complicated
rules. So in that sense, yes. Perhaps most importantly, it makes it easier
to change the implementation of how the rules are applied.
> - Is it compatible with lazy importing categories with axioms? (I am
> ready to believe that this can be made to work, but one has to be a
> bit careful in the join implementation).
I don't see any problem. Resolving the lazy import implicitly runs the
metaclass to assemble the new classes, but that never generates join
categories. Unless you manually construct a non-lazy join category in the
lazily imported module, but that is asking for trouble either way.
> - Will the proposal allow for getting rid of the global list of
> axioms/axiom names? If yes, how will the printing out be handled?
User-supplied axioms must be registered with the `axioms` factory object.
Printing uses `Axiom._repr_`, which you can override if you like (defaults
to `__class__.__name__`)
> - The proposal requires to get through the dictionary of the category
> classes, right? At first sight this is making me nervous (though not
> as much as if this was on instances). Is it guaranteed that this
> won't trigger accidently, say, lazy imports that might be there for
> other features (like functorial constructions)?
We only have to do instance/subclass checks. There are hooks in Python for
that, but they require a metaclass. In particular, lazy imports don't
implement them. Also `__instancecheck__` is the wrong way (would be called
on our metaclass) and `__subclasscheck__` does not give you access to the
instance.
> - Will some class binding with {{{__classget__}}} be still needed? If
> yes, how will the idiom {{{__base_category_class__ = Test1}}} work
> if {{{Test1}}} is itself a {{{CategoryWithAxiom/InnerCategory}}}?
I don't think we need `__classget__`, the whole design is to construct the
category class the way we want it on import. So there is no need to
redirect attribute access later on.
> - Where will the idiom {{{XXX.Finite()}}} be implemented? In particular,
> will introspection on {{{XXX.Finite?}}} work as it currently does?
Those are all methods that end up callling `XXX.with_axiom(Finite)`. They
are generated by the metaclass, so you can attach any doctstring you want.
For a dynamic category+axiom there won't be a static source code, of
course.
> - Where would be the natural place to put the axioms? If it's under
> {{{axioms.*}}}, how will potential name clashes be handled?
IMHO everything should go through the `axioms` factory object, which is
also where the order is defined. You can implement your axioms anywhere
you want. I've been trying to group them together by topic, though you
could use individual files. Doesn't matter as long as you use the factory
object.
--
Ticket URL: <http://trac.sagemath.org/ticket/10963#comment:501>
Sage <http://www.sagemath.org>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica,
and MATLAB
--
You received this message because you are subscribed to the Google Groups
"sage-trac" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sage-trac.
For more options, visit https://groups.google.com/groups/opt_out.