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