It's ALLLIIIIIVEEEEEEE!
Just kidding, that would be cool, though.
Status: Experimental
FrankenScript is a Partial Application utility for JavaScript.
Let's dissect addition and turn it into a monstrosity. Here is an explicit
addition function, plus
:
function plus(n,m) {
return n+m;
}
Very standard. Now, in order to mutilate arbitrary functions and
turn them into nightmares, we use Uhgg
.
var frankenPlus = Ughh(plus);
...which is pronounced groan. frankenPlus
can make for some pretty abbominable arithmetic! Watch in horror
as we attach the dismembered parameters and get our desired solution:
var frankenPlus1 = frankenPlus(1);
frankenPlus1(2);
➥ 3
frankenPlus1(3);
➥ 4
Now that frankenPlus
has the strength of a hundred functions, we can really be a
mad (computer) scientist! For instance, zipWith
:
var set1 = [1,2,3,4,5];
var set2 = [1,2,3,4,5,6];
zipWith(frankenPlus, set1, set2);
➥ [ 2, 4, 6, 8, 10 ]
or, equivalently with Underscore's map & element-wise application:
var plusN = _.map(set1, frankenPlus);
app(plusN, set2);
➥ [ 2, 4, 6, 8, 10 ]
Both zipWith
and app
are taken from Haskell.
Lo-Dash has a curry
function that does something similar to
the partial application examples above, but it blends between JavaScript's multiple parameters
and chained invocations. Now, I've included the same functionality so we can do fun stuffs like
this:
var plus4 = function (a,b,c,d){
return a+b+c+d;
}
var frankenPlus4 = Ughh(plus4);
frankenPlus4(1)(2)(3)(4);
➥ 10
frankenPlus4(1,2)(3,4);
➥ 10
frankenPlus4(1)(2,3,4);
➥ 10
I have an issue calling this curry
, because JavaScript's native multi-parameter function application
(,)
is not a tuple or product functor - it's not even a value, however it might be unique.
Regardless, you can't say it's the product functor universally, because it's not first-class. I'm going
to try and make a proper curry
/ uncurry
that respects the adjoint, but first I need a lambda
calculus.
We now have a very, very trivial method to declaring type signatures for your function. Observe:
var plusT = Ughh.typed("Number -> Number -> Number", function (n,m) {return n+m});
plusT;
➥ { [Function: func] typeSig: 'Number -> Number -> Number' }
plusT(1);
➥ { [Function: func] typeSig: 'Number -> Number' }
plusT(1)(2);
➥ 3
plusT(1)("foo");
➥ [Error: Parameter(s) does not match type signature]
- Hindley-Milner parametric polymorphism type inference
- Incremental (pseudo) type checking and signature declaration / binding
- Fixpoint termination with explicit recursion
- Lazy and Eager evaluation schemes