Last active
August 29, 2015 14:05
-
-
Save remydagostino/3919a92a538d5ffe8557 to your computer and use it in GitHub Desktop.
Curried Functions With Guards
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Do you think this might be a useful way to do functional programming | |
in Javascript? | |
Gaurded, curried functions are created like: | |
Lambda(2).case(predicate, expression).case(predicate2, expression2); | |
The `2` specifies that the function accepts two arguments, it will | |
be partially applied if it is called with fewer (just like autocurry) | |
Each case statement has a function which checks the inputs, if it | |
returns `true` then the expression will be called with the function | |
arguments. Only the first matching predicate is executed. | |
It would probably be better if the Lambda functions were immutable... | |
*/ | |
// Turns arguments into array | |
var argsToArray = function(args) { | |
return Array.prototype.slice.call(args); | |
}; | |
// Creates an auto-curried pattern matching function | |
// that can be extended with .case(predicate, expression) | |
var Lambda = function(numArgs) { | |
var guard, fn, tests; | |
tests = []; | |
fn = function() { | |
var i, test, result; | |
for (i = 0; i < tests.length; i++) { | |
test = tests[i]; | |
if (test.predicate.apply(this, arguments) === true) { | |
return test.expression.apply(this, arguments); | |
} | |
} | |
throw new Error('No matching case found for: ' + argsToArray(arguments)); | |
}; | |
guard = function() { | |
var args = arguments; | |
if (args.length < numArgs) { | |
return function innerGuard() { | |
var allArgs = argsToArray(args).concat(argsToArray(arguments)); | |
return guard.apply(this, allArgs); | |
}; | |
} | |
else { | |
// Call the function | |
return fn.apply(this, args); | |
} | |
}; | |
guard.case = function(predicate, expression) { | |
tests.push({ predicate: predicate, expression: expression }); | |
return guard; | |
}; | |
return guard; | |
}; | |
// Functor Map | |
var fmap = Lambda(2).case( | |
function(fn, a) { | |
return typeof fn == 'function' && Array.isArray(a); | |
}, | |
function(fn, a) { return a.map(fn); } | |
); | |
// Addition | |
var plus = Lambda(2).case( | |
function(a, b) { | |
return typeof a == 'number' && typeof b == 'number'; | |
}, | |
function(a, b) { | |
return a + b; | |
} | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment