Feature proposal: "Polymorphic `this` types"

Hi everyone,

I know there is the Haxe evolution repo, but it seems it is not meant for everyone to propose something there? So I try to suggest something here.

“Polymorphic this types” is a feature I learned from Typescript. Checkout this example (“pseudo” Haxe):

class BasicCalculator {
    public var result= 0.0;

    public function new () {}

    public function add( a: Int, b: Int): this {
        result += a + b;
        return this;
    }
}


class Calculator extends BasicCalculator {
    public function sin(): this {
        this.result = Math.sin(this.result);
        return this; 
           
    }
}

class Test {
    static function main() {
        var calculator = new Calculator();
        trace(calculator.add(2,3).sin().result);
    }
}

The clou is the return types of the functions BasicCalculator.add() and Calculator.sin(), which is this. Obviously this is not possible in current Haxe. But I hope the example makes it clear how useful this little feature would be. Check out the Typescript documentation for a more elaborate explanation:

https://www.typescriptlang.org/docs/handbook/advanced-types.html (there is a Paragraph called “Polymorphic this types”)

It would not be a very intrusive change, could even still fit in Haxe 3, since as far as I can tell it would not even break any existing code bases.

Hope it is I good place for a suggestion like that. If not maybe someone wants to point me where to post it instead.

Cheers

PS: love to new forum!

1 Like

Do you see a problem with doing this without specifying a type?

Such as:

class BasicCalculator {
    public var result= 0.0;

    public function new () {}

    public function add( a: Int, b: Int) {
        result += a + b;
        return this;
    }
}


class Calculator extends BasicCalculator {
    public function sin() {
        this.result = Math.sin(this.result);
        return this; 
           
    }
}

class Test {
    static function main() {
        var calculator = new Calculator();
        trace(calculator.add(2,3).sin().result);
    }
}

…I am just curious if there are any drawbacks to leaving it untyped

There’s an issue about it with some discussion here Self type · Issue #4474 · HaxeFoundation/haxe · GitHub, which was closed since it would require a haxe-evolution proposal. Why do you think it’s “not meant for everyone”?

That won’t work because BasicCalculator.add return type will be BasicCalculator as per type inference.

In that case, overriding a base class with a more specific type is something I’ve wanted to do in certain cases, but understand is not possible due to the nature of subclasses

class A {
    function foo():C;
}

class B extends class A {
    override function foo():D; // not allowed
}

...

var instance = new B ();
var value:C = instance.foo(); // is type D, not C

…unless it was smart enough to allow for overriding methods using a more restrictive type, which itself extends the original type. In this case, I would desire to see this work in a more general sense, not just the class name itself. For example:

class Object {
    function event():ObjectEvent;
}

class GameObject extends Object {
    override function event():GameEvent;
}

So long as GameEvent extends ObjectEvent, perhaps this would be possible, and nice to have?

Thanks @nadako. I was not aware that this proposal existed already. But yes, this seems to be the same.

I was thinking proposals on this repo are “not meant for everyone” because the Readme states “Haxe Proposals (HXP) can be submitted by any Haxe team developer or community member”. Unless I am a community member already without knowing :wink:

@singmajesty: overriding the return type of a function is actually not part of this proposal. Even though I agree that this would be a variant to solve the same kind of problem. But in my opinion not in the best way.

The this type seems to me like a very elegant solution. In Self type · Issue #4474 · HaxeFoundation/haxe · GitHub some commenters asking for a ‘proof of concept’. In Typescript we have a pretty good proof of concept, I think. It is in production and in the wild. It would be especially helpful in writing externs for untyped languages, btw.

I would also be interested in suggestions how to implement the provided ‘Calculator’ case with the current toolbelt of Haxe’s type system …without having to cast. I know there is kind of a way with type parameters, which looks ‘hacky’ to me though, to say the least. But maybe there are acceptable solutions?

Cheers

Community member is everyone else by default, including you (and me) :slight_smile:

Alright then… just created a pull request on the evolution repo. Let’s see what happen :wink:

Thanks @all.

@mak No problem :slight_smile:

Here’s the link to the proposal for future reference: Polymorphic `this` types by matulkum · Pull Request #36 · HaxeFoundation/haxe-evolution · GitHub

I don’t get what you’re saying. The example you gave works: Try Haxe!

IIRC ActionScript 3 actually didn’t allow for this, but in Haxe arguments types are contravariant and return types are covariant, as they should be.

Yeah, this might have changed in Haxe 3 or some point (because I remember this not being possible). Ignore my distracton