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

Suggestion to add "CFoldable" #245

Open
dmitriz opened this issue Apr 23, 2017 · 17 comments
Open

Suggestion to add "CFoldable" #245

dmitriz opened this issue Apr 23, 2017 · 17 comments

Comments

@dmitriz
Copy link

dmitriz commented Apr 23, 2017

In line with the discussion in ramda/ramda#2160, I wonder about the consensus to add CFoldable aka Commutative-Foldable, where reduce only needs to be defined and obey the laws for the commutative accumulators.

@i-am-tom
Copy link

The problem with this is that we can't impose commutativity on the function (which is what would need to be done for this to work). Honestly, I think the best option is to agree unanimously that objects simple aren't stable enough to be considered Foldable types. I'm not even sure they're stable enough to be considered Functor types!

@paldepind
Copy link

@dmitriz

I don't think an addition to the spec is necessary. Objects are foldable despite what the consensus in the linked Ramda thread is. It's easy to prove that Objects are foldable since you can easily implent reduce on them.

@i-am-tom

Honestly, I think the best option is to agree unanimously that objects simple aren't stable enough to be considered Foldable types.

Why not? Keys are stored in insertion order? I find that to be quite intuitive behavior and it certainly meens that a law abiding reduce can be implemented on Object.

@safareli
Copy link
Member

you just need to sort keys first https://github.com/sanctuary-js/sanctuary-type-classes/blob/master/index.js#L902

@i-am-tom
Copy link

@paldepind This is certainly not guaranteed https://stackoverflow.com/a/5525820/4022180, but @safareli's suggestion is the one that I have previously suggested as a best answer to this issue. However, given the lack of standard-enforced order, I do think that we can't (well, shouldn't) rely on the functor laws holding. Of course, a slightly lax instance is massively beneficial, so I think we should probably let it slide with a caveat - especially given that we can't (shouldn't) do equivalence with ordering anyway. The (lawful) practical incongruence is nil.

@paldepind
Copy link

paldepind commented Jun 26, 2017

@i-am-tom

This is certainly not guaranteed https://stackoverflow.com/a/5525820/4022180

Luckily for us that answer is wrong 😄 It's very unfortunate that misinformation is what people get from a Google search. SO is not a good source for such questions—looking directly at the spec is much better.

However, given the lack of standard-enforced order

The standard is very clear about enforcing order. It's described right here. The order described is the one you get from Object.keys, etc. As I said, normal non-numeric keys are given in insertion order, i.e. property creation order. Numerical keys like "12" are given in sorted order.

So, the correct answer to the SO question you linked is actually yes, if you define an object like this:

var obj = {};
obj.prop1 = "Foo";
obj.prop2 = "Bar";`

The spec absolutely guarantees that you will get the keys in insertion order if you iterate over them with Object.keys.

That is fantastic 😄 It means that if we want to we can make objects both foldables and functors.

Here is a nice article that breaks down what the spec states and confirms what I'm saying above.

@i-am-tom
Copy link

@paldepind These appear to be ES2015-specific links, which would suggest that this isn't the case before ES2015, which means this is surely still unreliable behaviour for BC reasons?

@paldepind
Copy link

paldepind commented Jun 26, 2017

@i-am-tom It has been implemented like that in all engines for a long time. Way before it found its way into the spec. So there is no issue with relying on it in code.

In fact the reason why it was added to the standard is that all engines had that behavior anyway and much code relied on it. So adding it to the spec was a win-win.

@i-am-tom
Copy link

@paldepind Oh, awesome! I had no idea :D Well, in that case, 👍 to your original message <3

@paldepind
Copy link

@i-am-tom

Well, in that case, 👍 to your original message <3

Nice, thank you 😄

@masaeedu
Copy link

masaeedu commented May 29, 2018

Should there perhaps be an extra laws only subclass of Semigroup called CommutativeSemigroup/CommutativeMonoid or something like that? CFoldable is then just Foldable with a stronger constraint on its foldMap.

@puffnfresh
Copy link
Member

Abelian (semi)group is another common name in mathematics.

@puffnfresh
Copy link
Member

I don't understand CFoldable though. Usually we'd just choose an order and move on. Can that not be done?

@masaeedu
Copy link

@puffnfresh Are you asking why CFoldable is needed instead of just using the commutative monoid with Foldable? The problem here is that more things are CFoldable than are Foldable. In fact every Foldable is also a CFoldable (passing a commutative monoid is fine where an arbitrary monoid is expected), but not vice versa.

@dmitriz
Copy link
Author

dmitriz commented May 31, 2018

@puffnfresh

I don't understand CFoldable though. Usually we'd just choose an order and move on. Can that not be done?

CFoldable is a different abstraction with different contract -- requiring commutativity for the function.

The problem with choosing the order,
it is not part of the abstraction normally associated with objects.
You would like to think of objects being equal regardless of their key insertion order.
You would like to feel safe to refactor your code from

var obj = {a:1, b:2}

to

var obj = {b:2, a:1}

However, with reduce depending on the key order, that refactoring is not safe.

The CFoldable spec should alert the user to the commutativity requirement,
in order to guarantee refactor safety and referential transparency.
(Just like traversable requires to work with applicatives.)

@puffnfresh
Copy link
Member

@dmitriz you are not safe to make that refactor. How does CFoldable change that?

@dmitriz
Copy link
Author

dmitriz commented Jun 1, 2018

@puffnfresh
By declaring the object as a CFoldable, which requires the function passed to be valued in commutative semigroup. Such as all, some, max, min, add and many others.
That makes reduce safe and you can refactor as above without any thinking.

Of course, this only affects the reduce method.
Other methods such as Object.keys are not as safe but they are not part of this spec.

@puffnfresh
Copy link
Member

@dmitriz I don't understand what is gained. You can refactor Foldable when you use a commutative function already. You can't change order of keys in a file because of Object.keys already.

I have motivations for CFoldable but I just don't think JavaScript Objects are one of them.

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

6 participants