zio / zio-prelude

A lightweight, distinctly Scala take on functional abstractions, with tight ZIO integration
https://zio.dev/zio-prelude
Apache License 2.0
449 stars 115 forks source link

Shoud Commutative extend Associative? #192

Open thesamet opened 4 years ago

thesamet commented 4 years ago

Looking at: https://github.com/zio/zio-prelude/blob/9bbfa4fd23b85b67f58b71c46ff4f7c85ab243c4/src/main/scala/zio/prelude/Commutative.scala#L8

There are commutative operations that are not associative, for example, the average of two numbers. I am still trying to grok the the code, but wonder if having Commutiative extend Associative is limiting the generality, or this is an an assumption intentionally made for the foreseen intended applications of this class.

adamgfraser commented 4 years ago

Yes you are definitely right that there are operations that are commutative but not associative. In an earlier version Commutative actually didn't extend Associative. Our perspective was that there are relatively few interesting operations that are commutative but not associative and there are costs to separating them in terms of then requiring more work to describe operations that are both commutative and associative.

I think the average of two numbers is actually a good example of that. It is commutative and not associative. But the fact that it isn't associative makes it not very interesting in a way from a compositional perspective. I can take the average of two numbers that way, but I can't take the average of three numbers by taking the average of two numbers and then averaging that with a third (at least without putting twice as much value as one as on the others). It seems like that would be better modeled as some kind of StatsCounter that kept track of a running total and number of observations internally, in which case it would be associative, commutative, and have an identity element.

denisgarci commented 4 years ago

Another operation that is commutative but no associative is floating-point addition due to rounding errors. See https://stackoverflow.com/questions/10371857/is-floating-point-addition-and-multiplication-associative

adamgfraser commented 4 years ago

Yes. So far we have had that perspective that it makes sense to define Associative instances for these types (see here) on the theory that if you are using floating point numbers you understand there can be rounding errors and it is not helpful to not provide instances that let you add them.