Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
Reduce<T> returns T instead of Option<T> #583
I was surprised to see that it throws an exception when
Wouldn't the functional approach be to have the return type be
Sure, the arguments are invalid. But isn't one of the design goals in functional programming to make invalid possibilities unrepresentable?
And isn't another goal to write pure functions? Enrico Buonanno on page 32 of Functional Programming in C# defines pure functions in part by forbidding them from throwing exceptions. By his definition, this function in impure.
It seems to me that we could change the types involved to more accurately convey what this function does...that is, to make this function pure.
My preference is still for option 1.
Here is the equivalent in Haskell:
Here is the equivalent in F#:
Both throw exceptions.
Changing this function to change the return type will break users' code. I am not against a
I like using and writing honest functions as Enrico defined them in section 3.2.3:
I don't see why other languages choosing to include impure/dishonest functions means that your library must do the same. In fact, my impression is that Language Ext is designed to do the opposite. Where C#/.Net provides
Certainly this would be a breaking change; there is no doubt about that.
Sure, one way to change an impure/dishonest function to one that is pure/honest is to weaken its output type. This is discussed by Enrico in section 3.4.5. However, this is not the only way. Another possibility is to strengthen the input types. Enrico discusses this in section 3.2.2. An example of this is the third change possibility that I listed above. Typically, I prefer to strengthen the input types, but in this situation with
We don't have dependent types, so it's not convenient to do this for every function. There always has to be a balance between ease of use and honesty. Just, like the
Actually, another aspect of this is the function really isn't as dishonest as you think. The signature clearly shows that it needs to return an
Sure, sometimes we need less safe options for pragmatic reasons.
Another design goal I see in functional programming relates to the names involved when there is a safe and an unsafe way to do something. I think the idea is that the shorter name, i.e. the one that is easier to read and write, is given to the safer approach.
For example, in F# records are immutable by default, so merely writing
specifies the safer approach. To specify the less safe approach, additional words are required, namely
If we added the function
What do you think about modifying the names so that the signatures would be like this?
Just my two cents: I had this question myself. But I don't have a solution therefore agree with Paul, for now.
I agree with @bender2k14 that this function doesn't feel pure. It's not about the fact that some inputs might throw an exception (like overflow in something like
Side note: Currently we cannot get full/dogmatic purism anyway because this is valid code, too:
Besides breaking changes I don't think
One could build a workaround by having another type like:
Then we could throw on
We could make this a bit more general adding
Obviously there is no big advantage calling this deconstructor (or some other operator like
We could also support some
Thinking in this direction this issue is related to #275 and the general question how to express non-empty sequences.
As said before: I don't see a practical general solution here -- even if we drop the compatibility aspect.
Regarding breaking code / compatibility: I personally would gladly accept the cost of changing my code if the new concept is definitely better, still easy to use and if I can be sure that old code wouldn't compile.