(function(global) {
    var types = function(obj) {
        throw new TypeError("fmap called on unregistered type: " + obj);
    };

    // inefficient as hell, but as long as there aren't too many types....
    global.Functor = function(type, defs) {
        var oldTypes = types;
        types = function(obj) {
            if (type.prototype.isPrototypeOf(obj)) {
                return defs;
            }
            return oldTypes(obj);
        }
    };

    global.fmap = curry(function(f, obj) {
        return types(obj).fmap(f, obj);
    });
}(this));