Sorin Miklós Zsejki | 30 May 19:27

How to "overload a function with static parameters"?

Let's say I have:

trait P end
trait R[\T extends P\] end
f[\T extends P\](p: T): R[\T\]

Now I add this:

trait SubP extends P end
trait SubR[\T extends SubP\] extends R[\T\] end

and I want an overloading of f like this:

f[\T extends SubP\](p: T): SubR[\T\]

This is not possible because the static parameters of f must exclude
each other. So my question is how to do this _without giving up the
static parameters_.

I know I could do something like:

trait R1 extends R end
trait R2 extends R excludes R1 end

and declaring f for R1 and R2, but what I want is a general
declaration of f and an overloading for the more specific cases like
SubP. I don't want the general case (the first 3 lines of code) to
make any reference to SubP or SubR.

I think with where clauses I could do something like:
(Continue reading)

Jan-Willem Maessen | 30 May 20:13
Favicon

Re: How to "overload a function with static parameters"?

On May 30, 2008, at 1:29 PM, Sorin Miklós Zsejki wrote:

> Let's say I have:
>
> trait P end
> trait R[\T extends P\] end
> f[\T extends P\](p: T): R[\T\]
>
> Now I add this:
>
> trait SubP extends P end
> trait SubR[\T extends SubP\] extends R[\T\] end
>
> and I want an overloading of f like this:
>
> f[\T extends SubP\](p: T): SubR[\T\]
>
> This is not possible because the static parameters of f must exclude
> each other. So my question is how to do this _without giving up the
> static parameters_.

If I've understood correctly, you can't.  If I pass a SubP to f,  
either overloading applies and either can be considered most  
specific.  Note that you *can* use an explicit typecase:

f[\T extends P\](p: T): R[\T\] =
     typecase p of
         SubP => ...
         else => ...
     end
(Continue reading)

Sorin Miklós Zsejki | 30 May 21:31

Re: How to "overload a function with static parameters"?

Thanks. How about the where clause? Does it make sense?

I have 2 problems with typecase:
1. The result of f always has the type R[\T\], even when I know it has
a runtime type of SubR[\T\].
2. All the cases have to be defined in the same component. I want to
have a default definition of f, then add other components with a
specialized implementation that statically returns a subtype of
R[\T\].

Of course, the root problem is that I am stubborn and insist of having
a return type as specific as possible for each case. Probably I will
end up with either defining different functions or using supertypes,
but I feel this should be "the right thing".

On Fri, May 30, 2008 at 9:13 PM, Jan-Willem Maessen
<Janwillem.Maessen@...> wrote:
> On May 30, 2008, at 1:29 PM, Sorin Miklós Zsejki wrote:
>
>> Let's say I have:
>>
>> trait P end
>> trait R[\T extends P\] end
>> f[\T extends P\](p: T): R[\T\]
>>
>> Now I add this:
>>
>> trait SubP extends P end
>> trait SubR[\T extends SubP\] extends R[\T\] end
>>
(Continue reading)

Guy Steele | 30 May 21:21
Favicon

Re: How to "overload a function with static parameters"?


On May 30, 2008, at 1:29 PM, Sorin Miklós Zsejki wrote:

> Let's say I have:
>
> trait P end
> trait R[\T extends P\] end
> f[\T extends P\](p: T): R[\T\]
>
> Now I add this:
>
> trait SubP extends P end
> trait SubR[\T extends SubP\] extends R[\T\] end
>
> and I want an overloading of f like this:
>
> f[\T extends SubP\](p: T): SubR[\T\]
>
> This is not possible because the static parameters of f must exclude
> each other. So my question is how to do this _without giving up the
> static parameters_.

Jan provided the correct answer to this, but I'd like to
amplify.  The naive model for how static parameters work
is that it is as if all possible instantiations of the statically
parametrized entity (trait, object, method, whatever) all
exist simultaneously, and it should behave exactly as if
you had written out all these possible instantiations
explicitly in your program.  (Of course, there might be an
infinite number of them, but let's ignore that point for now.)
(Continue reading)

Sorin Miklós Zsejki | 30 May 23:01

Re: How to "overload a function with static parameters"?

Thank you for the explanation, this way it is very easy to picture it.

Intuitively, if B is a subtype of A, I can imagine that:
f(x: A) = x + 1
stands for:
f(a1) = a1 + 1
f(a2) = a2 + 1
...
f(b1) = b1 + 1
f(b2) = b2 + 1
...
and that:
f(x: B) = x + 2
stands for:
f(b1) = b1 + 2
f(b2) = b2 + 2
...
where a<number> are instances of A and b<number> of B, but there is a
convention for choosing the second form for b1 because B is more
specific than A, just as SubR would be more specific than R. Very
naively, I tend to generalize this to the type variables based on the
type they extend, but I am aware that in practice this is much more
complicated. This is way over my head anyway; for example, I've just
found out about the Z notation reading the Fortress specification.

Anyway, I'm a big fan, and with where clauses, getters/setters, and
other features in the beta spec, Fortress will be even better.

On Fri, May 30, 2008 at 10:21 PM, Guy Steele <Guy.Steele@...> wrote:
> [...]
(Continue reading)


Gmane