Skip to content
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

implementation #1

Open
davidchambers opened this issue Nov 22, 2016 · 10 comments
Open

implementation #1

davidchambers opened this issue Nov 22, 2016 · 10 comments

Comments

@davidchambers
Copy link
Member

Start with the type of map as defined by the Functor type class:

map :: Functor f => f a ~> (a -> b) -> f b

Replace Functor f => f with Function x:

map :: Function x a ~> (a -> b) -> Function x b

Replace Function $1 $2 with ($1 -> $2):

map :: (x -> a) ~> (a -> b) -> (x -> b)

Rename type variables:

map :: (a -> b) ~> (b -> c) -> (a -> c)

Here's the implementation from sanctuary-type-classes:

//  Function$prototype$map :: (a -> b) ~> (b -> c) -> (a -> c)
var Function$prototype$map = function(f) {
  var functor = this;
  return function(x) { return f(functor(x)); };
};

We should add something similar to the readme:

//  Function#map :: (a -> b) ~> (b -> c) -> (a -> c)
Function.prototype.map = function(f) {
  var g = this;
  return function(x) { return f(g(x)); };
};

It's worth noting that this is different from the implementation in your tweet, @puffnfresh. Unless I'm mistaken your version does not have a type compatible with fantasy-land/map.

@JAForbes
Copy link
Member

JAForbes commented Nov 22, 2016

Would usage be something like?

const pythagoras = 
  ap([square]) // [9,16]
  .map(sum)  // 25
  .map(Math.sqrt) // 5

pythagoras([3,4]) //=> 5

@davidchambers
Copy link
Member Author

I don't understand what's going on in your example, @JAForbes. Here's a straightforward example:

> Math.abs.map(Math.sqrt)(-64)
8

> Math.sqrt(Math.abs(-64))
8

@davidchambers
Copy link
Member Author

Oh, I see it now. ap is a curried binary function. Nice!

@JAForbes
Copy link
Member

I like the simplicity of your example @davidchambers. I think in the readme we'll need lots of simple examples that solve some concrete problems. If anyone has any ideas, please post away.

@puffnfresh
Copy link
Member

@davidchambers my tweet was wrong, thank you!

@safareli
Copy link
Member

safareli commented Nov 25, 2016

If this is goint to be a proposal, I think we would need to also support this and multiple arguments:

Function.prototype.map = function(f) {
  var g = this;
  return function(...args) { return f(g.apply(this, args)); };
};
obj = {
  foo: 1,
  bar: function(a) {
    return this.foo + a
  }.map(Math.sqrt)
}

obj.bar(3) // 2

@nadameu
Copy link

nadameu commented Jun 2, 2017

@i-am-tom has written an excellent series of blog posts about Fantasy Land.
In Functions as Functors he implements Function.prototype.map, Function.prototype.ap and Function.prototype.chain, and explains their usefulness through simple and practical examples.

  • map: for function composition;
  • ap: allows using simple functions in liftN operations;
  • chain: simple Reader implementation.

@i-am-tom
Copy link

i-am-tom commented Jun 2, 2017

Funnily enough, @gabejohnson is pushing for Function.prototype.compose in fantasyland/ECMAScript-proposals#1, and I'm thinking more and more that these two should be unified.

Variadic arguments would be unlawful (if we're thinking about map as meaning, "what we can do with a functor"). Similarly, compose has the same problem. However, if we push for something like pipe (which isn't such a loaded term), all of these things can be derived more strictly from that base, while simultaneously not upsetting those outside of FP by imposing unary function restrictions.

Given the ten minutes of thought I've applied, this seems like a compromise that could be accepted by both parties. My preference for this is purely because it's going to be difficult to push anything functional on the larger JS audience without bastardising it, which would be a shame.

Thoughts?

@JAForbes
Copy link
Member

JAForbes commented Jun 5, 2017

However, if we push for something like pipe (which isn't such a loaded term), all of these things can be derived more strictly from that base, while simultaneously not upsetting those outside of FP by imposing unary function restrictions.

I like this approach. It allows us to be less concerned about functions being lawful, without harming chances of having lawful implementations in the distant future when the value of lawfulness has been proven out in the mainstream.

@jedwards1211
Copy link

If this is a proposal for ECMAScript, you might want to speak the language: use Flow or TypeScript-like syntax for describing types instead of Haskell syntax.

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

No branches or pull requests

7 participants