Comments (7)
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')))
from fantasy-land.
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.
from fantasy-land.
I'd really like lift
behaving like:
Value.lift(x) = Value.of(x)
Value.lift(f, x) = Value.of(f).ap(x) = x.map(f)
Value.lift(f, x, y) = Value.of(autocurry(f, 2)).ap(x).ap(y) = x.map(autocurry(f)).apply(y)
Value.lift(f, x, y, z) = ...
So if value has lift
you can fantasy fill map
, of
and ap
:
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:
seq
is from #50
and I'd call monadic join squash
so it doesn't clash so badly.
from fantasy-land.
I gotta say, your graphics are awesome!
from fantasy-land.
@joneshf, thanks, those you learn to do in the university ;)
And one addition might be to have tfil
, flippled lift, so your applicative parser could be like:
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 where
, as I leave the pure combinator hanging after the applicative expression:
braces p = f <$> string "(" <*> p <*> string ")"
where f _ x _ = x
from fantasy-land.
I think we should revisit this (I want to implement it :-)).
Making a liftA2
(or liftF2
) function the alternative definition of Apply
seems very attractive (would be placed at seq
in @phadej's diagrams). I guess that it's more often needed than ap
. Of course they can be derived from each other, but making lift
is a bit ugly in JS as it requires currying.
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: ax.apWith(f, ay)
sounds wrong because we're not applying ax
but rather f
, and I really don't want to build upon thrush
or T-combinator (see this SE question for references).
Of course, a variadic liftN
function might be even more useful (easier to implement and call). It's quite common in libraries, e.g. as combineWith
in Bacon, or join
in Bluebird. There are versions that optionally take arrays as inputs instead, and I think that's a route we could go down as well to make a proper binary function (array + fn), as we've seen that generic libraries like Ramda which use currying don't really like variadic functions. Yet after all this might fit better with Applicative than in Apply (which cannot handle the nullary case), and in this case I think we might just introduce an optional sequence
function that could be used like
sequence([ax, ay, az, …]).map(function([x, y, z, …]) {
…
});
which already looks a lot like that tfil
idiom that was suggested. Implementing sequence
in a library is probably much more efficient than deriving it as
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([]));
}
from fantasy-land.
Is this going to happen, or should I close it for now?
from fantasy-land.
Related Issues (20)
- [Question] Type signature for ap HOT 2
- Adding Folktale to implementations.md
- Equivalent for Serial typeclass? HOT 1
- Is really necessary specify "No parts of <...> value should be checked"? HOT 11
- Add Traversable1 HOT 3
- Help understanding use of identity in Traversable laws HOT 2
- Fantasy Land specification version number HOT 1
- Switch to Symbols HOT 2
- Wrong argument in Traversable HOT 4
- Is monet.js compatible? HOT 1
- Why FL specifies the ChainRec typeclass when there is the trampoline monad? HOT 7
- What does "and" mean? HOT 2
- Can someone explain me how I should understand Semigroup? HOT 5
- Remove all OOP features HOT 21
- Traversable and Foldable use multiple variables as arguments HOT 12
- Profunctor should require Contravariant HOT 10
- Implementation of `Compose` is confusing HOT 3
- should Chain properties depends on fantasy-land/ap (and possibly .map)? HOT 4
- Why putting "fantasy-land/" before everything in readme? HOT 3
- Is `Pair` a valid instance of `MonadRec`?
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fantasy-land.