#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 nthiery):

 Replying to [comment:501 vbraun]:
 > 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.

 This ambiguity is already resolved by the fact that you are
 implementing a category with axiom (which you know from the
 inheritance from Finite.Category).

 > 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.

 If you have concrete examples to test, I am interested! The only
 constraints that you have to respect is that the
 {{{extra_super_categories}}} methods should return strict super
 classes. As for diagnosing, you can check the stack and see which
 {{{extra_super_categories}}} methods got involved. Admittedly not for
 a beginner, but I don't expect a beginner to implement non trivial
 categories with axioms anyway.

 > 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.

 Anyway you want, except using the same name as for the axiom if you
 still want to support {{{.Finite()}}} without {{{classget}}} magic! I
 believe being able to use the same name is a feature. And it's
 consistent with what's done for functorial constructions.

 > It seemed natural to not restrict to a single axiom, but thats just a
 by-product.

 Ok!

 > 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.

 Sounds reasonable! Of course we don't yet save on placeholder category
 classes on the dynamical side.

 > > - 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.

 You mean, upon computing the join of {{{Magmas()}}} and
 {{{AdditiveMagmas()}}} you would go through the factory object, and
 that object would have a rule to construct
 {{{MagmasAndAdditiveMagmas()}}}? Can such a rule be implemented with a
 good complexity?

 > 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.

 The only thing is to make sure, upon adding a bunch of axioms to a
 given category, that you have lazy imported exactly those files needed
 so that the manager is aware of all the relevant axiom
 categories. Given that you still go through the current join, that
 should be alright.

 > 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__`)

 Sorry for the ambiguity: I am speaking of the printing of the category
 with axiom classes. From what I see below, there still is a global
 list of axioms, so we can use that; the only difference is that it's
 created on the fly through a registering process. We could trivially
 do the same with the current infrastructure. But it gets tricky when
 we want to explicitly choose a given order to get nice printing.
 Probably we want some mixed strategy, with the most important axioms
 explicitly ordered in a single point of the code, and the others added
 on the fly later.

 > 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.

 Ok.

 I am still reluctant with that business. When we implement
 Groups.Finite, it's about the finite groups category. And I believe
 the magic, if any, should reside in the nested class and not in
 Groups. For otherwise, we should do the same for consistency for
 functorial constructions. And if we want later to add yet another type
 of construction, beyond axioms and functorial constructions, the
 metaclass of Groups will have to handle all of them, instead of having
 each nested class just handle its own specifics. So much for
 separation of concerns.

 > 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.

 Except to allow for the same name for the category with axiom and the
 {{{.Finite}}} method.

 > > - 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.

 It matters in that you'll have to import them explicitly; so this
 calls for some recommended scheme; otherwise we will spend time
 searching for them.

 Thanks for your answers! It clarifies the situation. Now I still
 believe it belongs to a later ticket, and I am not yet

 Cheers,
                              Nicolas

--
Ticket URL: <http://trac.sagemath.org/ticket/10963#comment:502>
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.

Reply via email to