Giter VIP home page Giter VIP logo

Comments (7)

SimonRichardson avatar SimonRichardson commented on August 18, 2024

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.

russellmcc avatar russellmcc commented on August 18, 2024

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.

phadej avatar phadej commented on August 18, 2024

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:
methods derivability graph
seq is from #50
and I'd call monadic join squash so it doesn't clash so badly.

from fantasy-land.

joneshf avatar joneshf commented on August 18, 2024

I gotta say, your graphics are awesome!

from fantasy-land.

phadej avatar phadej commented on August 18, 2024

@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

methods

from fantasy-land.

bergus avatar bergus commented on August 18, 2024

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.

SimonRichardson avatar SimonRichardson commented on August 18, 2024

Is this going to happen, or should I close it for now?

from fantasy-land.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.