[Haskell-cafe] Where do trivial functions on the usual containers live?

MarLinn monkleyon at gmail.com
Sun Dec 20 13:39:25 UTC 2020


> I am looking for a place where I can find or put some simple functions that I
> expect but do not find in the `containers` or elsewhere in the standard
> libraries.

For now, I can't see a good place for any of your suggestions. But maybe 
even discussing potential why-not's may further the discussion.


> * Group a collection by an equivalence relation:
>
>        classify ∷ Ord π ⇒ (a → π) → [a] → [[a]]

If the provided function is indeed an "equivalence relation", shouldn't 
the type be Eq π ⇒ (a → π) → [a] → [[a]], which is basically 
Data.List.groupBy? On the other hand if the resulting list is supposed 
to be ordered, most practical applications will probably use a set or a 
map anyway.

So the difference between this function and existing functionality is so 
small, that the cost of maintenance and remembering the name might not 
be worth it.


> * From a finite map, get a map from its range to its fibers:
>
>        fibers ∷ (Ord k, Ord v) ⇒ Map k v → Map v (NonEmpty k)

Why NonEmpty, and not Set? Or any Monoid? And more importantly, who are 
we to decide? Again, the cost difference between maintaining and 
re-discovering one "standard" vs. re-implementing something more 
precisely suited to the task at hand via (e.g.) Data.Map.foldMapWithKey 
doesn't seem worth it.

Additionally if I'm writing a program that would benefit from this 
function, performance considerations will almost always lead me to not 
use it. Instead, I will maintain both the map and its inverse from the 
start.


> * Put a type into the diagonal of its square:
>
>        diagonal = λx → (x, x)

Now this might fit into Data.Tuple. Then again, it's faster and more 
self-documenting to re-implement it at hoc than to remember a name.

Also, this (again) is less useful than it seems. It will almost always 
require an application of uncurry as well, which makes the program 
harder to understand. Sometimes it's better to replace both with a 
single application of the Monad instance of (->) – or with the "real" 
function.

For example:

uncurry (+) . diagonal ≡ join (+) ≡ \x -> x + x ≡ (2*)

Using diagonal is probably one of the worst ways to implement this and 
many of its brethren.


> It is unfeasible to put them into the standard libraries. _(Attempts were made.)_

This sounds like the maintainers of the standard libraries had their own 
objections. I suspect some of them might be similar to the ones above. 
Which leads me to suspect you might not have taken their feedback to 
heart. Which might in fact be the biggest hurdle on getting your code 
accepted into a library.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20201220/cbbab76d/attachment.html>


More information about the Haskell-Cafe mailing list