So I've been learning myself some Functional JavaScript and the only thing not easily supported obvious in it is defining Data Types as in Haskell or what not. The most common implementation is to use prototyping as means of achieving it as with the Maybe Monad or what have you.

While I have no problem with the prototyping style, I just find that exposing the type as a object encourages me to use method chaining and exposing state unnecessarily is a bit uncomfortable. What I would like is that given a module, only the module can manipulate its values.

Some code might make this easier to visualize.

// A data type to represent an list of size two
var Pair = {
    create: function (first, second) {
        return Object.freeze([first, second]); // You think it's untouchable?
    },

    first: function (pair) {
        return pair[0];
    },

    second: function (pair) {
        return pair[1];
    }
};

var myPair = Pair.create('key', 'value');

myPair[0] = 'hacked key'; // Will not work
myPair[1] = 'hacked value'; // Ditto

So nothing is wrong with this and you can be justified just by using Object.freeze to make things immutable. What I am worried about is dirtily copying the object and passing it through the module functions without going through its create function which seems dirty.

var copiedPair = [pair[0], pair[1]]; // I find it dirty that I can access the contents easily

console.log(Pair.first(copiedPair)); //Which I find somewhat disturbing

As you can see above, I have two problems. First, you can recreate the type value so easily without abandon. Second is that you can pass the hacked object in and no one would know the difference. The idea is that by using objects, they can easily be mimicked and exposed even if you make them immutable.

I may be too paranoid but I like it when there is a little contract between the modules and types, nothing directly accessible but the interfaces. So how do we do it without JavaScript's powerful object type? Well the help of functions!

Instead of using objects to represent types, let's use functions to represent it instead. But how? Thunking may seem a good idea.

var create = function (first, second) {
    return function () { // Thunk it good
        return Object.freeze([first, second]);
    };
};

var myFunctionPair= create('newKey', 'newValue');

var actualPair = myFunctionPair(); // Give it to me!

But the problem remains, how do we shield access to it? We can create a token of sort to prevent it from being accessed without it.

// Let's assume we have a secret type token
Pair.secretToken = Object.create(null); // Quick way to create symbols in JavaScript

var tokenCreate = function (first, second) {
    var state = Object.create([first, second]);
    return function (accessToken) {
        return accessToken === Pair.secretToken ? state : null; // Or throw an error but that's evil
    };
};

var tokenPair = tokenCreate(1, 2);

tokenPair(); // :: null
tokenPair(Pair.secretToken); // :: [1, 2]

So by giving the type module a secret symbol or token, we can effectively hide the state of the type value. Cool. We can make it better by putting it the module's closure so that no one else can access it.

var generateSymbol = Object.create.bind(null, null); // Quick shiv

var stateHolder = function (emptyValue, token, state) { // Let's enhance it a bit
    return function (accessToken) {
        return accessToken === token ? state : emptyValue;
    };
};

var TypeModule = (function (typeToken) {
    var Type = Object.create(null);

    Object.assign(Type, {
        create: function (first, second) {
            var state = Object.freeze(first, second);

            return stateHolder(null, typeToken, state);
        },

        first: function (pair) {
            return pair(typeToken)[0];
        },

        second: function (pair) {
            return pair(typeToken)[1];
        }
    });

    return Object.freeze(Type);
}(generateSymbol()))

So we solved out problem, more or less, but did we just write more paranoid code than what it can afford? I don't know but I like it so let me formalize it a bit.

// Main Type Module
var Type = (function () {
    var generateSymbol = Object.create.bind(null, null);

    var stateHolder = function (emptyValue, token, state) { // Let's enhance it a bit
        return function (accessToken) {
            return accessToken === token ? state : emptyValue;
        };
    };

    var Module = generateSymbol();

    var emptyTypeValue = generateSymbol();

    var typeHolder = stateHolder.bind(null, emptyTypeValue);

    Object.assign(Module, {
        typeValue: function (token, value) {
            return typeHolder(token, value);
        },

        define: function (constructor) {
            var typeToken = generateSymbol();

            var typeDefinition = constructor(typeToken);

            return Object.freeze(typeDefinition);
        }
    });

    return Object.freeze(Module);
}());

var Pairs = Type.define(function (typeToken) {
    var pairValue = Type.typeValue.bind(null, typeToken);

    return {
        create: function (first, second) {
            return pairValue(Object.freeze([first, second]));
        },

        first: function (pair) {
            return pair(typeToken)[0];
        },

        second: function (pair) {
            return pair(typeToken)[1];
        }
    };
});

If by any chance you didn't like the part that you had call the type value function with the token each time, we can intercept all the type functions such that when any of the arguments is of the said token type it is automatically converted for us; that is we don't really care about the token, we just want the value.

var mapObject = function (f, object) {
    var mappedObject = Object.create(null);

    Object.assign(mappedObject, object); // A weird fix here when hasOwnProperty is present

    Object.keys(object).forEach(function (key) {
        var value = object[key];

        mappedObject[key] = f(value, key);
    });

    return mappedObject;
};

var mapIf = function (p, f) {
    return function (value) {
        return (p(value) === true) ? f(value) : value;
    };
};

var isFunction = function (value) {
    return typeof value === 'function';
};

var isTypeValue = function (value) {
    return true; // Some criteria to determine if the function is an ordinary or typed one
};

var typeToken = Object.create(null); // The actual type token, just stubbed here for example

var TokenLessPair = mapObject(mapIf(isFunction, function (typeFunction) {
    return function (/* args */) {
        var args = [].slice.call(arguments),
            remappedArgs = args.map(mapIf(isTypeValue,
                                          function (typeValue) {
                                              return typeValue(typeToken)
                                          }));

        return typeFunction.apply(null, remappedArgs);
    }
}));

So with that intercepter, there is no need to worry about the token, it is hidden as implementation detail. There are problems with this though such as performance overhead, side effects if there are and probably more. But again, this still works if everything is simple… which is not the case most of the time.

The secret sauce should be how to distinguish normal and special typed function but if there is a distinction, it gets harder to compose these typed functions if we are not careful. For now this makes me feel good, maybe I should write Monads with it. Till then, I'll see what I can dig up with it.

So that's what I thought of in a few hours. What else can we do with this style? Derived types as in Haskell? Maybe we can try that in the next post. For now with just a few lines of code, we created some base types good enough for some basic modules. I'm not trying to make the ultimate type library, just something vanilla JavaScript can do for the paranoid functional programmer.