#10963: More functorial constructions
-------------------------------------+-------------------------------------
       Reporter:  nthiery            |        Owner:  stumpc5
           Type:  enhancement        |       Status:  needs_review
       Priority:  major              |    Milestone:  sage-6.1
      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                |       Commit:
   Dependencies:  #11224, #8327,     |  8045aa4a4b7ada735b3eb6055382f9b341a39f1e
  #10193, #12895, #14516, #14722,    |     Stopgaps:
  #13589, #14471, #15069, #15094,    |
  #11688, #13394, #15150, #15506     |
-------------------------------------+-------------------------------------

Comment (by nthiery):

 Replying to [comment:396 vbraun]:
 > Nowhere does the source of `Sets.Finite` refer to `Cs.Finite` or vice
 versa. By the normal mental model of Python code (principle of least
 astonishment), that ought to mean that the implementations are
 independent. The only thing that ties them together ultimately is that a
 substring of the type name matches.

 May I play the advocate of the devil? Consider this example:
 {{{
 class A:
     def foo():
         ...

 class B(A):
     def foo()
         ...
 }}}

 Nothing ties ``B.foo`` to ``A.foo``. Yet, by standard OO mental model,
 we know that B.foo() overrides A.foo() and should thus have the same
 semantic.  Yet, ultimately the only link between the two is that the
 substring ``foo`` of the names ``A.foo`` and ``B.foo`` matches.

 Granted, the relation "inheritance" relation between ``Cs`` and
 ``Sets`` is not as explicit as between ``B`` and ``A``; but that's the
 price we pay for all the flexibility of dynamic mixins.

 For example the following would make me much happier since it makes the
 dependence visible:
 > {{{
 > sage: class Cs(Category):
 > ....:     def super_categories(self):
 > ....:         return [Sets()]
 > ....:     class Finite_or_any_other_name(Sets.Finite):
 > ....:         class ParentMethods:
 > ....:             def foo(self):
 > ....:                 print "I am a method on finite C's"

 I see your point. We have something similar for functorial
 constructions where the idiom is:
 {{{
 > sage: class Algebras(Category):
 > ....:     class Graded(GradedModulesCategory):
 > ....:         class ParentMethods:
 > ....:             def foo(self):
 > ....:                 print "I am a method on graded algebras"
 }}}

 The reason why I moved away from this idiom, and why I consider
 refactoring functorial constructions similarly, is that defining new
 axioms is much more lightweight in practice than defining new
 constructions.  Really it was getting in my way when writing
 code. Itching hard. In fact Jean-Baptiste is complaining that it's
 still not lightweight enough :-) Also, even just implementing an axiom
 in a category is more lightweight than implementing a functorial
 construction (no need to fiddle with an extra import and risk merge
 conflicts there, ...).

 There is another annoying issue in being explicit about where the
 axiom is defined as in the idiom {{{Finite(Sets.Finite)}}}. Namely, if
 later on one wants to generalize the axiom by moving its definition up
 the category hierarchy (maybe because in the meantime a larger
 category has been implemented where the axiom makes sense), then you
 need to fix accordingly each and every category where the axiom is
 implemented (the usual price for redundant information). This
 situation has happened to me in practice more than once!

 > You could argue that the `ParentMethods` / `ElementMethods` are
 already precedent for magic attribute names that violate the usual
 python mental model. Thats true, but a) I wasn't asked when they were
 introduced

 But this was reviewed by a bunch of people. Of course not as great as
 you, master :-)

 Sorry, I could not resist. I totally understand your being careful
 before being imposed upon a framework that may have long lasting
 consequences on our code. But it's super frustrating for me and all
 those who have tons of code depending on that framework.

 >  and b) there are only two magic names that are ubiquitous
 in every category source. So it is still kind of obvious from the
 source code. But if you end up with precisely two categories that have
 a ''Flasque'' subcategory, say, then it is going to be very confusing.

 Well, you see Flasque(CategoryWithAxiom) in Cs. It tells you that it's
 implementing an axiom named Flasque axiom. If you are interested at
 the code of Cs, there are some chances that you know what Cs is about
 and are aware of this axiom. And otherwise you quickly lookup
 {{{Cs().Flasque?}}} to know what it's about.

 Granted this assumes a minimum of knowledge about categories and
 axioms. Like any infrastructure there is a minimum of stuff to learn
 before you can really benefit from it. Here a 30 minutes course should
 be sufficient to cover the necessary ground.

 Cheers,
                            Nicolas

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