More on Constructors in Haxe

What's bugging me about constructors is making things easy for people to guess where they can get things.

What I'd like

Type.Constructor(args);

This isn't, for various reasons, an option. For example:

typedef SomeObject = { 
 final value : String;
}

Has no runtime representation: SomeObject is not a value

Which makes sense, typedefs don't have reflection either, they are compile time structures.

abstract AnotherObject(String) from String{

}

If you try to reference an abstract like AnotherObject without one of it's members, you get Cannot use abstract as value, which makes sense because at runtime what is happening is that the member functions of AnotherObject are being called with a value of it's delegated type.

A Fix of Sorts

Haxe happily handles phantom types, so we can use this, with a little boilerplate to get something predictable:

enum TAG<T>{
    TAG;
}

You can fox the system by constructing the phantom type through typing your function explicitly.

static public function AnotherObject():TAG<AnotherObject>{
    return TAG;//compiler will not complain, and pattern matching works.
}

To make this more accessible I use a [wildcard](https://github.com/ohmrun/stx_nano/blob/develop/src/main/haxe/stx/nano/Wildcard.hx), which because of the way Haxe publishes enum constructors plus the way static extensions work gives us a space to create predictable constructors.

var a = __;
$type(a);//Wildcard

and a static extension pivoting on the wildcard value:

class AnotherObjectCtr{
    static public function AnotherObject(wildcard:Wildcard):TAG<AnotherObject>{
    return TAG;
}

and can be used like this:

final ctrs = __.AnotherObject();
$type(ctrs);//TAG<AnotherObject>

And if you want to add to the list of constructors, you can do so as follows:

using AnotherObjectCtrMembers;

class AnotherObjectCtrMembers{
    static public function unit(tag:TAG<AnotherObject>):AnotherObject{
        return ("test":AnotherObject);
    }
}

and the whole thing looks like:

using stx.Nano;
using AnotherObjectCtr;
using AnotherObjectCtrMembers;

function test_ctr(){
    final v = __.AnotherObject().unit();
    $type(v);//AnotherObject
    trace(v);//"test"
}

Running code here