fantasy-land: Apply composition law does not equate

It could be that my implementation is not correct, but here’s the result of the test.

test.js

"use strict";

class Thing {
  constructor(value) {
    this.value = value;
  }
  ap(other) { return other.map(this.value); }
  map(f) { return new Thing(f(this.value)); }
}

const y = new Thing(x => x);
const left = y.ap(y.ap(y.map(f => g => x => f(g(x)))));
const right = y.ap(y).ap(y)

console.log("left === right:", left === right);
console.log("left value:", left.value.toString());
console.log("right value:", right.value.toString());

Running test.js

$ node test
left === right: false
left value: g => x => f(g(x))
right value: x => x

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 16 (11 by maintainers)

Most upvoted comments

Similar to Function#apply or a curried Function#call.

Don’t contaminate your thoughts with this sort of comparison. 😉

I suggest comparing ap to map. They’re very similar:

> Thing(9).map(Math.sqrt)
Thing(3)

> Thing(9).ap(Thing(Math.sqrt))
Thing(3)

The type signatures are instructive:

map :: Functor f => (a -> b) -> f a -> f b
ap  :: Apply f => f (a -> b) -> f a -> f b

ap exists in Prelude as well.

λ: ap [(*10),(*100),(*1000)] [1,2,3]
[10,20,30,100,200,300,1000,2000,3000]