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

Maybe class "map" function doesn't compose #615

Open
ChuckJonas opened this issue Mar 26, 2021 · 2 comments
Open

Maybe class "map" function doesn't compose #615

ChuckJonas opened this issue Mar 26, 2021 · 2 comments

Comments

@ChuckJonas
Copy link

ChuckJonas commented Mar 26, 2021

In chapter 8, Maybe is defined as follows:

class Maybe {
  static of(x) {
    return new Maybe(x);
  }

  get isNothing() {
    return this.$value === null || this.$value === undefined;
  }

  constructor(x) {
    this.$value = x;
  }

  map(fn) {
    return this.isNothing ? this : Maybe.of(fn(this.$value));
  }

  inspect() {
    return this.isNothing ? 'Nothing' : `Just(${inspect(this.$value)})`;
  }
}

Then an example is provided using a . style:

Maybe.of({ name: 'Boris' }).map(prop('age')).map(add(10));
// Nothing

However, it's been brought to my attention that this is not a "lawful" use of a functor because it doesn't compose?

const f = (v) => v.name;
const g = JSON.stringify;
const fandTheng = (a) => g(f(a));
const user = { name: null };
console.log(
  Maybe.of(user).map(f).map(g).inspect(),  // Nothing 
  Maybe.of(user).map(fandTheng).inspect()  // Just(null) 
); // not equal, breaks the law of composition!

I haven't finished the book so sorry if this is address further on.

PS: I think the inspect method has a bug in the recursion as this example will break it.

@ChuckJonas ChuckJonas changed the title Maybe "map" function doesn't compose Maybe class "map" function doesn't compose Mar 26, 2021
@hugh-lx
Copy link

hugh-lx commented Aug 31, 2021

I'd be remiss if I didn't mention that the "real" implementation will split Maybe into two types: one for something and the other for nothing. This allows us to obey parametricity in map so values like null and undefined can still be mapped over and the universal qualification of the value in a functor will be respected. You'll often see types like Some(x) / None or Just(x) / Nothing instead of a Maybe that does a null check on its value.

Because of the simplified implementation, there are no Just(null) and Just(undefined).
There is no recursion in Maybe.prototype.inspect. And inspect is weird in Firefox.

@sevillaarvin
Copy link

I'd be remiss if I didn't mention that the "real" implementation will split Maybe into two types: one for something and the other for nothing. This allows us to obey parametricity in map so values like null and undefined can still be mapped over and the universal qualification of the value in a functor will be respected. You'll often see types like Some(x) / None or Just(x) / Nothing instead of a Maybe that does a null check on its value.

Because of the simplified implementation, there are no Just(null) and Just(undefined). There is no recursion in Maybe.prototype.inspect. And inspect is weird in Firefox.

I couldn't understand that paragraph. Thank you for explaining it clearly.

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

3 participants