Why not Pointed?
|(One intermediate revision by one user not shown)|
Latest revision as of 04:26, 4 September 2013
Edward Kmett, the author of category-extras, pointed, and many related packages, has since moved his focus to semigroupoids and semigroups. He finds them more interesting and useful, and considers
Pointed to be historical now (he still provides the pointed package only because “people were whinging”).
Expanded/improved information from Edward Kmett
To be fair, that assessment is a bit of a simplification of my position. ;) A slightly less simplified version of my position is that Pointed has no useful laws and almost all applications people point to for it are actually abuses of ad hoc relationships it happens to have for the instances it does offer. The one law Pointed offers is how it interoperates with fmap:
fmap f . point = point . f
but this is a free theorem of the type, so Pointed does not need Functor as a superclass, and now, unlike at the time of the original Typeclassopaedia when I first pushed Pointed on the community, it no longer has the superclass. Most usecases folks claim for it have to do with things like making sets of valus with constructions like 'foldMap point' but there we're relying on an ad hoc relationship because we happen to know what this does operationally for (Set a). At first blush one might think it generalizes. After all, if we substitute [a] then we get a list of all of the elements, right?
But when you go to drop in Maybe all of a sudden we're getting Just the result of smashing together the results as a Monoid. or Nothing. Not anything at all sensible. Without knowing the concrete instances you're getting for Monoid and Pointed you know nothing about the behavior.
The notion of a semigroupoid on the other hand gives you an associativity condition and can be used to drive many useful operations. You can 'foldMap1' a non-empty container with a semigroup. You can 'traverse1' a non-empty container with a mere Apply (semi-applicative) instance. You can use it to do interesting zip-like things to maps.
Including Pointed in the hierarchy comes at a cost. Including the semiapplicative (Apply)/semimonad (Bind) tiers would come at a cost.
If you fully fleshed out the lattice of them you'd indeed get some finer grained control over what you could do with the standard classes. For instance lens would be able to give real types to affine traversals given Pointed -- one of their few legitimate uses!
However, this comes at the price that you no longer really get to define good mutual definitions for these things. The full lattice.
3.) Functor + Pointed -- this is free theoremed, no class needed
4.) Functor => Apply -- associativity law
5.) Apply + Pointed => Applicative -- class needed, unit laws
6.) Apply => Bind -- inhabited by Map k, IntMap, etc.
7.) Bind + Pointed => Monad
takes the user up to having to define 6 classes before breakfast just to get to Monad and back up to the functionality he had in 3 lines before we started tinkering with his code. Worse, some of these tiers are uninhabited by methods, they merely offer laws.
Laws that newer users may not understand are critical to the correctness of their code, and which won't be pushed on them when they get a bag of constraints out of the typechecker. So the user can silently introduce code that relies on constraints it hasn't put properly on the type.
There is also an understandable undercurrent in the community that having to deal with so many classes would be a bad idea.
So this leads us to consider either a.) default superclass systems that can try to take some pain out or b.) removing layers from our über-system of classes. No extant default superclass proposal deals well with complex lattices, due to multiple candidate default definitions conflicting.
So we try to focus on a few good abstractions, rather than capturing them all. Pointed has a bad power to weight ratio and induces people to write code they can't reason about.
Or you can just say "people were whinging” =)