Where do trivial functions on the usual containers live?

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. Many hackage contributors seem to maintain their own <maintainer>-utils package containing bits and bobs they personally deem useful but can not find elsewhere. I might add my own one soon. Not saying this is a good thing, though.
Some examples I have in mind:
* Group a collection by an equivalence relation:
classify ∷ Ord π ⇒ (a → π) → [a] → [[a]]
GHC.Exts.groupWith or Data.List.groupBy might do want you want, depending on whether you want to aggregate globally or only consecutive runs of equivalent elements.
* 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)
The usual Semigroup instance of Map k v destroys data upon key collision. For problems like this I have a newtype wrapper newtype SemiMap f v = SemiMap {getSemiMap :: f v} instance (Semigroup v, Ord k) => Semigroup (SemiMap (Map k) v) so that one can implement 'fibers' using foldMapWithKey. Is this worth its own package?
* Put a type into the diagonal of its square:
diagonal = λx → (x, x)
This may be too trivial to be a library function, and its proper type should rather be x -> Pair x since we know both components have the same type. Pair is a Monad and this function is its return. In package ghc Pair has an Applicativeinstance at least. Regards, Olaf

December 21, 2020 8:19 PM, "Olaf Klinke"
The usual Semigroup instance of Map k v destroys data upon key collision. For problems like this I have a newtype wrapper
newtype SemiMap f v = SemiMap {getSemiMap :: f v} instance (Semigroup v, Ord k) => Semigroup (SemiMap (Map k) v)
You might like the monoidal-containers package, which newtypes the unordered-containers and containers types to have instances like `instance (Semigroup v, Ord k) => Semigroup (MonoidalMap k v)`. -- Jack
participants (2)
-
jack@jackkelly.name
-
Olaf Klinke