[Aldor-l] "has" and "with" and bug

Christian Aistleitner tmgisi at gmx.at
Mon Aug 20 09:50:14 EDT 2007


Hello,

On Mon, 20 Aug 2007 13:22:22 +0200, Ralf Hemmecke <ralf at hemmecke.de> wrote:

>>> If you call
>>>
>>>    f(Fraction Integer)
>>>
>>> then R = Fraction Integer
>>
>> More precisely, we know that
>>
>>   R: Ring == Fraction Integer.
>>
>> So,
>>
>>   R: Ring == some_right-hand_side
>>
>> . And that is indeed of the same shape as we had in the previous code
>>
>>   Dom: with {} == some_right-hand_side
>>
>> .
>
> Obviously,
>
>    R: Ring == Fraction Integer
>
> and
>
>    R: Ring == Fraction Integer add
>
> is not the same thing.

That's not obvious to me.

   Fraction Integer

builds a domain.

   Fraction Integer add

builds a domain (although typically stored somewhere else in memory).

So whats the difference?
Both are of the same shape:
>>   R: Ring == some_right-hand_side

Could you elaborate on the difference?
(I know the latter forumulation typically throws away unneeded categories,  
but that's not of importance here, as its about difference between global  
constants and constants used as function parameters)

> In fact, I don't know exactly, how the first is
> to be interpreted. Can someone show me whether for the first case R
> should be of category Field?

R is an identifier of type Ring--nothing more. (Compare AUG 8.13)
But since I fear we might not be discussing the same things, let me come  
back to the notion of static and dynamic types.

R is an identifier of type Ring. Hence, R has static type Ring.
Especially, R is not of type Field. Hence, R does not have static type  
Field.

R refers to the domain Fraction Integer.
Hence, R's dynamic type is the type of Fraction Integer.
R's dynamic type satisfies Field.

>>> If you call
>>>
>>>    f(Fraction Integer)
>>>
>>> then R = Fraction Integer
>>> and (as I understand it)
>>>
>>>    f(R: Ring): ...
>>>
>>> simply means that whatever you plug in to f must (at least) be of 
>>> category Ring. Inside the body of the function, the actual exports of 
>>> the domain you plug in are taken.
>>
>> No. Consider the following counter example:
>>
>>   #include "algebra"
>>   f( R: Ring ):() == {
>>     import from R;
>>     1 / 1;
>>   }
>>   f( Fraction Integer );
>>
>> fails to compile with
>>
>>   "demo.as", line 4:   1 / 1;
>>                      ....^
>>   [L4 C5] #1 (Error) There are no suitable meanings for the operator  
>> `/'.
>
> I would have guessed so.
>
>> . However, replacing "R: Ring" by "R: Field" compiles and works:
>>
>>   #include "algebra"
>>   f( R: Field ):() == {
>>     import from R;
>>     1 / 1;
>>   }
>>   f( Fraction Integer );
>>
>> In both cases, "the actual exports of the domain you plug in" are the
>> same. However, the first piece of code does not work.
>
> As you know "has" accesses the type of the actual parameter that is
> plugged in into the function. It can do that because it is evaluated at
> runtime. For your example, at compile time the meaning of "/" must be
> clear. That is completely independent of what you plug in to f(...).

So you are trying to say that R has a type at compile time (Ring).
And the value to which R refers to at runtime may have a different type.
Is this correct?

The type of R at compile time is typically called static type.
The type of R's value at run-time is typically called dynamic type.

So here we go again:
"has" checks for the dynamic type, not the static type.

In

   A: B == C add D

, A is of static type B. The type of "C add D" is A's dynamic type.

Let's relate this to my stripped down version of the original problem of  
this thread:

   #include "aldor"
   import from String, TextWriter, Character;

   Dom: with {
   } == add {
     privateFunc(): () == {}
   }

   main(): () == {
     stdout << "Dom has 'privateFunc' ? " <<
       (Dom has with {privateFunc: ()->()}) <<
       newline;
   }
   main();

You've been curious, why the result of this code is "T".

The reason is that "Dom" has static type "with {}" and dynamic type "with  
{privateFunc: () -> ()}".

>> You can tell Aldor to _not_ export a function by adding "local" to the
>> definition of the function.
>
> Completely clear. But what do I do then if someone has written a domain
> that exports some functionality that I don't want to have. Simple
> example: I want to rename a function.

You cannot achieve this easily. Is something like this commonly used  
somewhere?

> Let's say someone has implemented a domain A that exports (and
> implements in the "add" part exactly the functions
>
>    foo: % -> %
>    +: (%, %) -> %
>
> and nothing else.
>
> What should
>
> B: with {foo:%->%; *:(%,%)->%} == A add {*: (%,%)->% == +}
>
> export?

Nothing, because it should not compile. (+$A) is of type
   ( A, A ) -> A
and not of type
   ( B, B ) -> B
. But I did not write this to mack about your example, but to show that  
your harmless looking code should actually be longer. Thereby, the  
difference to the formulation hiding the "+" I give later on is not that  
drastic.
But let's assume, you meant something like

B: with {
   foo:%->%;
   *:(%,%)->%
} == A add {
   Rep == A;
   import from Rep;

   *( a: %, b: %): % == {
     per ( (+$Rep) ( rep a, rep b ) );
   }
}

Then B's static type should be

   with {
     foo: % -> %;
     *: ( %, % ) -> %;
   }

B's dynamic type should be

   with {
     foo: % -> %;
     *: ( %, % ) -> %;
     +: ( %, % ) -> %;
   }

> How would you rewrite that with your understanding of how things should
> work?

B: with {
   foo:%->%;
   *:(%,%)->%
} == add {
   Rep == A;
   import from Rep

   foo( a: % ): % == {
     per ( (foo$Rep) ( rep a ) );
   }

   *( a: %, b: %): % == {
     per ( (+$Rep) ( rep a, rep b ) );
   }
}

That's nasty. I fully agree. But Aldor never (as far as I know) had in  
mind to encourage obscure things like renaming of functions...

Kind regards,
Christian




More information about the Aldor-l mailing list