-
Notifications
You must be signed in to change notification settings - Fork 40
Open
Description
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
Labels
No labels