Function equality

I was ready to let this wind down having gotten early on Evan’s definitive view that he would prefer functions be declared equal if they computed the same thing which really is impossible to compute. I just think that then argues for a type system mechanism to prevent such equality checks from sneaking into the code.

But I stirred the hornet’s nest and it seems some of my explanations for why this might matter have lead to more confusion.

First, on crashes, I refer again to message 5 in this thread. Function equality check crashes in Elm fall into a category that is both potentially detectable at compile time (unlike stack overflow) but aren’t caught. They can’t be caught at module load time the way cyclic references are. Instead, you have to actually perform the comparison and not have it short-circuited by referential equality. The net result is that this is a path to what could have been preventable crashes in production. It also leads to incidents like the recent case of someone here being puzzled at why comparing HTTP requests could crash. To understand why, you have to know that Decoders are basically wrappers around functions.

Second, utility and performance. From a performance standpoint, lazy HTML demonstrates the value of caching. What if one wanted to build a caching mechanism for something else? For example layout computations that could not be handled by HTML or queries filtering down a dictionary full of items or subscription computations. But more broadly, the thing that characterizes functional programming languages is that they are much more friendly to building data structures that include functions as a first class component. See, for example, the discussion earlier in this thread about building dictionaries with the comparison function baked into the data structure. But if function equality checks can crash, then these need to be treated as second-class data structures ineligible for equality tests.

Finally, solutions. There seem to be three ways out if one doesn’t just accept the risks inherent in the current state of affairs. One is a type-system mechanism to prohibit function equality tests and hence equality tests of anything containing functions. One is to just use referential equality for functions. In practice, this will work but it does break some ability to reason about programs since it breaks referential transparency. And one is something like the structural equality definition I outlined which has the downside of being harder to compute with Elm’s current JavaScript implementation.

And with that summary, barring any significant new arguments — I really did find the point about >> semantics interesting to consider — I will now just tell myself that I’ve already pointed to all of the key issues.