Re: [open-axiom-devel] [fricas-devel] ModMonic and the Rep voodoo
A system for computer algebra and symbolic mathematics
Brought to you by:
dos-reis
From: Gabriel D. R. <gd...@cs...> - 2011-10-24 17:02:56
|
Waldek Hebisch <he...@ma...> writes: | Gabriel Dos Reis | > | > | > Consider the definition of ModMonoid: | > --------------8<---------------8<----------------8<-------------- | > )abbrev domain MODMON ModMonic | > ++ Description: | > ++ This package \undocumented | > | > ModMonic(R,Rep): C == T | > | <snip> | > Its description does not have a claim for "author", but the intersection | > of authors of domains using this domain leaves me with Johannes Grabmeier :-) | > | > | > ModMonic is not a builtin domain, therefore one needs a definition of its | > representation, i.e. a definition for "Rep", is needed. Yet, none is | > provided. Rather, "Rep" here is specified as a parameter to the functor. | > (That is not the same as defining it locally to some value) | | Hmm, I am not sure what difference makes defining: | | ModMonic(R,RepT): C == T | | and later | | Rep := RepT that is the brownie point (and what I did internally). There are fundamental differences. First, because of the principle of abstraction, parameter names are and should be immaterial. Surely, you do not want your functions or constructors to start behavingly differently just because you happen to consistently rename its parameters. | but IMHO passing Rep as argument is resonable shortcut for the above. There is a well established practice and programming technique of passing the representation as a parameter (or the subdomain or the base domain) as a parameter. They are not just called "Rep" :-) | If there are differences in behaviour I would rather change compiler | so that they agree. | | BTW: AFAICS there is no need to have Rep at all -- all Rep does is | allowing magic coercions between % and Rep. Let me clarify. There ought to be a way of saying what the representation domain is. The AXIOM book documents that you need the "special variable Rep", as stated in section 13.6 titled "Representation". The official grammar in section 13.2 (page 528) lists assignment to Rep as the first thing. Aldor thinks of "Rep" as a distinguished *constant*, not a parameter. Speaking of the "magic coercions", if you write in the original AXIOM Rep == RepT instead of Rep := RepT you would not get the same thing, and the domain will not compile. Consequently, you need Rep in practice in AXIOM and Aldor. [the reason why the '==' version won't work is that the compiler would think it is a macro form, therefore won't give Rep an abstract definition that it gives to all parameters, and when it comes back later to ask whether there was a definition of Rep, it won't see it. A compiler implementation detail leaks out. ] In a different version of AXIOM, one may think of different way of specifying what the representation domain is; but there needs to be a way to say what the representation domain is. The distinction (or lack thereof) between Rep and % is what causes miscompilation in some old AXIOMs programs (as we discussed recently) where an infinite recursion is introduced, and therefore forces explicit $Rep. Aldor does not have that problem. | > Now, consider the capsule-level variable "power". It is declared as | > | > power:PrimitiveArray(%) | > | > then later assigned to as | > | > power := new(0,0) | > | > There are two lexical occurences of the literal '0' in there. Can you | > guess, which one is which? There are at least five interpretations for | > each constant: | > | > 0: R -- the parameter R satisfies Ring | > 0: Rep -- the parameter Rep satisfies UnivariatePolynomialCategory(R) | > 0: % -- the current domains satisfies same | > 0: NonNegativeInteger | > 0: Integer | > | | Well, 'power' is declared to be of type 'PrimitiveArray(%)' so 'new' | should produce 'PrimitiveArray(%)' and compiler searches for it | in 'PrimitiveArray(%)'. And indeed, in 'PrimitiveArray(S)' we | have: | | new : (NonNegativeInteger, S) -> % | | So the first argument to 'new' must be 'NonNegativeInteger' and the | second must be '%'. 1. new, expects its second *argument* to be of type %. It does not require that there be no implicit coercion between the argument as lexically written in the source code, and the actual code generated for that argument. If one thinks that the mere presence of the parameter "Rep" indicates that is the representation domain, therefore the implicit coercion from Rep to % is OK, then 0@Rep is a good viable candidate. 2. Fortunately, in this case, 0@% is also defined explicitly to be 0$Rep, but there is no requirement that be the case. And when it is not, we get a problem. 3. ModMonic(R,Rep) satisfies UnivariatePolynomialCategory(R), so that means that there is alsoanother implicit coercion that turns 0@R into a legitimate value of type %. 4. Similar reasoning holds for 0@Integer because % satisfies Ring, and there is an implicit coercion from Integer to any domain that satisfies Ring. 5. Since NonNegativeInteger is a subdomain of Integer, it also provides an implicit coercion. So, in fact if one thinks that the mere presense of the parameter Rep is sufficient to indicate representation domain and therefore implicit coercions, then we have a legitimate case of ambiguity. Think about it. | > That this domain compiles at all is mysterious; it happens to depend on | > a very obscure implementation detail of AXIOM compilers, one that is not | > advertised at all -- and I don't think it should. | > It is voodoo. So, I am calling it Johannes's Rep voodoo :-). | | I would not call this voodoo: the compiler performs reasonable type | inference. There is nothing reasonable about it. The way that most AXIOM compilers do overload resolution (even in faces of ambiguity) is to pick the first from a list that makes the compilation works, regardless of whether the arguments are the best or not. That list does not necessarily follow any principles that relates the arguments to the call, e.g. exact match or requiring fewer implicit coercions, etc. It is just how they happen to be put on an internal list. | Sometimes compiler works too much to make sense of | user input, but IMHO this is not the case. Unfortunately, this is one of those cases. We are lucky that it works at all; that is why it is voodoo. -- Gaby |