Variadic Constructors in Haxe

Thinking about how to improve Haxe's function dispatch I came across something usable which could even be encoded within the current type system.

Languages like Julia have variadic dispatch on constructors, which makes for some simpler code. The way we could address that in Haxe is as follows:

  1. Shortlex ordering on Types and Expr

This is doable, and it allows laying out macro Expr and Type in a stable order meaning predictable outcomes

  1. Args as Enums

It's not tricky to munge your argument types into a readable EnumItem name

enum TypeArgSum<P,R>{
  TypeStringArg(s:String);
  TypeFun1RArg(fn:P->R);
}
  1. Pattern matching on Arg instances via an abstract
abstract MyTypeArg<P,R>(MyTypeArgSum<P,R>) from MyTypeArgSum<P,R> to MyTypeArgSum<P,R>{
  public function new(self) this = self;
  @:noUsing static public function lift<P,R>(self:MyTypeArgSum<P,R>):MyTypeArg<P,R> return new MyTypeArg(self);

  @:from static public function fromMyTypeStringArg<P,R>(s:String):MyTypeArg<P,String>{
    return lift(MyTypeStringArg(s));
  } 
  @:from static public function fromMyTypeFun1RArg<P,R>(fn:P->R):MyTypeArg<P,R>{
    return lift(MyTypeFun1RArg(fn));
  }
}
  1. A lift function that calls the actual constructor different ways depending on the EnumValue. First let's define some type
class MyType<P,R>{
  public dynamic function maker(p:P):R{
        return value;
    }
    public var value : Null<R>;
    public function new(?maker,?value){
        this.maker = maker ?? this.maker;
        this.value = value;
    }
}

And then, using something based on a shortlex ordering, you could construct something like the following:

@:to public inline function bump():MyType<P,R>{
        return switch(this){
            case MyTypeStringArg(s)         : new MyType(null,s);
            case MyTypeFun1RArg(fn)        : new MyType(fn,null);
        }
    }

Doing this inside the compiler doesn't require any more type architecture and would allow for variadic dispatch on constructors.

Runnable code here