
On Thu, Feb 18, 2016 at 6:24 AM, Henrik Nilsson
As to making tuples functor instances, that can only be done by arbitrarily imbuing one of the fields with a special status. I have to ask: Why? After all, taking pairs as an example, the *essence* of a pair is that there are two projection functions, one for each field.
So, if I am now interested in applying a function to the fields, why should only one of the fields be granted that privilege? That's just not symmetrical and goes against the very idea of tuples.
There’s nothing symmetrical about a type constructor with two distinct type variables wherein only one of them is the last. Perhaps you would prefer tuples to be two-element HLists, which would be isomorphic given proper type selections but would work very much differently at the type level. Any type constructor such as data Pair a b = Pair a b will necessarily have the same «privilege» granted to the last type variable. It’s the reason things like data Const a b = Const a behave as they do. Such distinctions are involved in the underlying mechanisms for monad transformers and lenses to work as they do.
And whenever I have wanted to map on tuple fields (which I do from time to time), I most certainly want the ability to map on any field.
Anyone with a couple of decades of Haskell experience ought to understand that the desire to map on any field of a record cannot be served by a typeclass such as Functor. You may reasonably disagree with folding and traversing over degenerate cases such as tuples, but surely you must agree that there cannot be any other way to map over tuple fields with fmap. You may even disagree with the existence of the Functor instance or the pretension to use Functor to map over the last field in a tuple, but this instance is used by a lot of people in contexts where it brings clear benefits and has a very clear meaning.
As to tuples as instances of foldable: Why? There isn't any structure to fold!
Because it is standard practice in mathematics and programming to give uniform treatment to degenerate cases. This does sometimes come in conflict with usability and intuition. This kind of problem occurs in many contexts. There are similar discussions among mathematicians and engineers on the parity of zero, the value of 0⁰, what the first natural number is, etc, with various degrees of consensus and controversy.
By all means, if some care about making tuples be instances of functor and foldable etc., put those instances in a separate module, thus saving the rest of the (Haskell) world from the cognitive burden of even beginning to make any useful sense of
length (1, 2) = 1
I would expect that anyone with a couple of decades of Haskell experience would see without much effort that the transitive, implicit importing of type class instances would entirely defeat the idea of trying to isolate these instances. You would get them in your code if you ever imported anything that has in its transitive closure any module that imports them. Avoiding them would require changing the fundamental mechanism for type class instance visibility (which is one of Haskell’s unique features and brings too many benefits to ignore just over some apparent quirk), or avoiding depending on a large portion of Hackage. Surely you must see how this is unreasonable: instance absence in practice requires community consensus, and these instances have a well-defined, unique, useful, correct definition.