-
Notifications
You must be signed in to change notification settings - Fork 376
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Just an idea: Why not make LiftN
the requirement for applicatives rather than ap
?
#56
Comments
Can you propose a implementation, so then we can move the discussion on. As you say I don't think we'll provide a way to overload the arguments of ap... although @puffnfresh might have a different idea? One possible way is if you know some of the arguments before the method call is to provide a bind: var id = require('fantasy-identities');
var f = function(a, b, c, d) {
console.log(a, b, c, d);
}
var unshift = function(f) {
return function() {
// horrid state :(
var x = [].slice.call(arguments)
x.unshift(x.pop());
return f.apply(null, x)
};
}
var a = id(unshift(f).bind(null, 1, 2, 3))
console.log(a.ap(id('a'))) |
well, the implementation would of course have to be applicative-specific. I've demoed the three suggestions proposed for 'option' (aka 'Maybe') with some examples here (apologies, I don't actually know javascript so the example is in coffeescript with auto-generated javascript). https://gist.github.com/russellmcc/9357418 I think 'join' and 'lift' are probably the two most sensible choices for primitives (of course they are closely equivalent), but the point I was making with ap is that it's easy to extend the existing semantics to support multiple arguments. |
I'd really like
So if value has Value.of = Value.lift; // if you don't want to check arity
Value.prototype.map = function (f) {
return Value.lift(f, this);
};
Value.prototype.ap = function (x) {
return Value.lift(apply, this, x); // apply from fantasy-combinators
}; The other direction is also possible, though not so trivial Value.lift = function (f) {
if (arguments.length <= 1) {
return Value.of(f);
} else if (arguments.length == 2) {
return arguments[1].map(f);
} else {
f = autocurry(f, arguments.length - 1);
var x = arguments[1].map(f); // should we wrap this to not break on Array?
for (var i = 2; i < arguments.length) {
x = x.ap(arguments[i]);
}
return x;
}
}; So you can derive methods like in: |
I gotta say, your graphics are awesome! |
@joneshf, thanks, those you learn to do in the university ;) And one addition might be to have function braces(par) {
return Parser.tfil(Parser.str("("), par, Parser.str(")"), function (a, b, c) {
return b;
});
} IMHO it's might more readable, and maybe "more idiomatic" JavaScript. Kind of inspired by Haskell's braces p = f <$> string "(" <*> p <*> string ")"
where f _ x _ = x |
I think we should revisit this (I want to implement it :-)). function ap(af, ax) {
function call(f, x) { return f(x); }
return lift(call, af, ax);
}
function lift(f, ax, ay) {
var f_curried = function(x) { return function(y) { return f(x, y); }; };
return ax.map(f_curried).ap(ay);
} I don't think we should make this a method though but rather a static function, and I cannot really envision a name for it either: Of course, a variadic sequence([ax, ay, az, …]).map(function([x, y, z, …]) {
…
}); which already looks a lot like that function sequence(arr) {
return arr.reduce(function(ar, ax) {
return ar.map(function(res) {
return function(x) {
res.push(x);
return res;
};
}).ap(ax);
}, of([]));
} |
Is this going to happen, or should I close it for now? |
It seems like in a language like JavaScript where currying isn't the norm (and might not be performant because of a lack of compiler help), it might be more useful to make something more like
LiftN
the requirement for applicative rather thanap
. It could even be backwards compatible for non-library code by just allowingap
to take multiple arguments like this:This would be fairly easy to implement for most applicatives I can think of, and would certainly be more convenient for the user and probably more performant, too.
If this doesn't match the aesthetics of fantasy-land (and my guess is it doesn't), maybe there should be a way for implementors to optionally provide a
liftN
method (under some friendlier name, maybe justlift
) for performance reasons?The text was updated successfully, but these errors were encountered: