Skip to content
This repository has been archived by the owner on Jan 26, 2022. It is now read-only.

Include an .ap/Applicative method with this propsal #10

Closed
dtipson opened this issue Mar 30, 2016 · 10 comments
Closed

Include an .ap/Applicative method with this propsal #10

dtipson opened this issue Mar 30, 2016 · 10 comments

Comments

@dtipson
Copy link

dtipson commented Mar 30, 2016

This proposal essentially gives native Arrays the methods they need to work as Monads (without having to extend the prototype). Given that once .flatMap is implemented, implementing an .ap/Applicative method/interface is trivial, it seems like a worthwhile addition to the namespace (for the same reason as flatten/flatMap appeal to me: it implements the core algebraic methods necessary for chainable computations instead of requiring people to either extend the prototype or abandon using Arrays directly when they want those sorts of operations).

Array.prototype.ap = function(a) {
  return this.flatMap(f => a.map(x=>f(x)) );
};

That would allow you to apply an array of data to an array of functions and get back all the results (or, if the functions are curried, do so with several chained applications of arrays). Very useful and elegant for things like graphing/plotting, generational mutations of data, etc.

var curveOne = x=> [x, (x+1)*(x+2)];

var curveTwo = x=> [x, (x+3)];

[curveOne, curveTwo].ap([1,2,3,4,5]);//-> Array of [x,y] coordinates for curves on a graph
@ljharb
Copy link
Member

ljharb commented Mar 30, 2016

Is there a name you would suggest that isn't as obscure and unapproachable as "ap"?

@dtipson
Copy link
Author

dtipson commented Apr 5, 2016

.ap is used by the primary spec for these sorts of things in javascript. Apply would be a first choice of course, but also totally unworkable since that already means something else in terms of javascript namespaces. We're treading in very tight confines in terms of choosing names that aren't used elsewhere with differing type-signatures, so ap seems like a good compromise since it already has considerable backing in the FP community.

@bterlson
Copy link
Member

bterlson commented Apr 6, 2016

All else aside, Is there a strong reason why .ap shouldn't stand as a separate proposal? I am in favor of keeping this as constrained as possible.

@dtipson
Copy link
Author

dtipson commented Apr 8, 2016

I think the case is this: adding just .flatten() as a standalone by itself would be sensible. But once implemented, it naturally makes an implementation of .flatMap() immediately and trivially possible, hence why those are sensibly being proposed together. But then, by the same logic, adding .flatMap() also makes .ap() immediately and trivially possible (i.e. along with .map(), these methods share common traits that allow them to all be very easily defined in terms of other). Avoiding having people modify the prototype to gain access to all these closely related methods, so that they can be used as a common computational interface, would be a win.

Against this proposal would be if flatten/flapMap ultimately differ in their implementation from the other major alegraic specs, then it would probably be better for .ap not to be included, or to be included under a different name, because that namespace is already used/defined on lots of other libraries with strongly defined interfaces (i.e. they currently use .chain instead of .flatMap because they're wary of breakage from exactly this sort of change).

@ljharb
Copy link
Member

ljharb commented Apr 8, 2016

One difference, however, is that flattening (via Array#concat) and flatMapping (via Array#concat and Promise#then) are both patterns that already exist in the language - the flatten and flatMap methods make these existing patterns more explicit and useful. I'm not aware of any existing patterns that accept multiple functions, and invoke them all (lots of things take one callback, and Promise#then takes two, but only invokes one) - please correct me if I've overlooked something?

@dtipson
Copy link
Author

dtipson commented May 17, 2016

An applicative interface doesn't accept multiple functions: it applies a container of values (which, ok, those can also be functions, but that's not a common case) to a/some functions that happen to be in the same type of container. In the case of Arrays, just as you might want to have a list of primitive values, in a language where functions are first-class, you might also want to have a list of functions (e.g. a list of active data transformations to make to a given dataset). This comes in handy for things like statistics, probability, graphing, and complex rendering applications like canvas/WebGL and a common pattern in the functional programming style.

It also sort of "completes the circle" for Arrays in a set of possible, related transformations, allowing you to create higher-order operations in the full range of possible (but highly generalized) ways necessary to match up whatever their inner types are in chained operations, without the interfaces themselves having to know anything about the inner types they're managing.

@ljharb
Copy link
Member

ljharb commented May 17, 2016

@dtipson right, but JS has no generic "apply" behavior for values, only Function#apply for functions.

@dtipson
Copy link
Author

dtipson commented May 17, 2016

And this is just applying values to functions that happen to be in a container... in this case, in an Array. It's just a type elevation of these same concepts, in the same way that flatMapping is an elevation of mapping (i.e. it allows you to apply values in a container(Array) to a function that returns containers(Array) instead of values).

@robotlolita
Copy link

.applicativeMap is a better name than .ap.

@michaelficarra
Copy link
Member

I'm going to close this to keep this proposal as minimal as possible. If there is demand for Array.prototype.applicativeMap, we can have another proposal for it.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants