Skip to content

New standard for creating algebraic data types. #55

@adit-hotstar

Description

@adit-hotstar

I'd like to propose a new standard for creating algebraic data types. Consider the following.

const Maybe = {}; // Static Land Canonical Module

const Nothing = (() => {
    function Nothing() {}
    Nothing.prototype["static-land/canonical"] = Maybe;
    return new Nothing; // Singleton Pattern
})();

function Just(value) {
    if (this instanceof Just) this.value = value;
    else return new Just(value); // Hack for calling the constructor without `new`.
}

Just.prototype["static-land/canonical"] = Maybe;

The primary advantage of defining algebraic data types like we did above, is good console logs.

> Nothing
Nothing {}
> Just(10)
Just { value: 10 }

Pattern matching is also standardized. You can use pattern matching with built-in types too.

Maybe.map = (mapping, maybe) => {
    switch (maybe.constructor.name) {
        case "Nothing": return Nothing;
        case "Just": return new Just(mapping(maybe.value)); // Using `new` for performance.
    }
};

We can also create a utility function which makes defining new data constructors less verbose.

const data = (type, name, ...keys) => {
    const {length} = keys;

    function Data(...vals) {
        if (this instanceof Data)
            for (let i = 0; i < length; i++)
                this[keys[i]] = vals[i];
        else return new Data(...vals);
    }

    Object.defineProperties(Data, {
        name:   { value: name },
        length: { value: length }
    });

    Data.prototype["static-land/canonical"] = type;

    return length > 0 ? Data : new Data;
};

This makes it easy to define new data constructors for algebraic data types.

const Maybe = {};

const Nothing = data(Maybe, "Nothing");

const Just = data(Maybe, "Just", "value");

I would love to hear your thoughts on this, and continue the discussion in #45 here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions