[Haskell-cafe] Please add a method for optimized concat to the Semigroup class

Yitzchak Gale gale at sefer.org
Tue May 3 21:43:27 CEST 2011


Edward Kmett wrote:
> sconcat :: [a] -> a -> a
> with either the semantics you supplied or something like
> sconcat = appEndo . mconcat . map diff

The sconcat we have been discussing is

sconcat = flip $ appEndo . getDual . mconcat . map (Dual . Endo . flip (<>))

(avoiding the use of Dual.diff.Dual so that we don't need to define
dualUnDual or some such messiness)

> But it was somewhat unsatisfying, in part because of the need for a seed
> element.

Only because, as you said, there is no standard non-empty list type.

> Another unsatisfying detail is no definition is in any way shape or form
> canonical when folding over a list.

While our definition doesn't look any better than the others
when expressed in terms of those combinators, it certainly
seems to be the most natural when defined directly
as Holger did. It's also the direct analogue of mconcat when
viewed as the same type with lists replaced by non-empty
lists. I'm sure that's the definition most users will expect.
But I would be happy with whichever you supply.

> ...I'm more than happy to add it if only for
> symmetry with Data.Monoid, but I'd be much happier doing
> so with a compelling example where it actually sped things up

I'm currently doing some recognition algorithms on heterogeneous
collections of graphical elements on a 2D canvas. Many types of
elements have a location and a rectangular extent. You can often
combine them, but there is no unit element because even an
empty element needs to have a specific location. It would be very
slow to combine a list of them incrementally; instead, you find
the minimum and maximum X and Y coordinates, and combine
the content using a fast algorithm.

(I originally used Monoid instances by augmenting types with
locationless empty elements. But that made a mess of my code
and introduced a myriad of bugs and potential crashes. These
are definitely semigroups, not monoids.)

I'm sure there are countless other natural examples of semigroups
in the wild, and that the typical non-trivial ones will benefit
from an optimized sconcat.

Thanks,
Yitz



More information about the Haskell-Cafe mailing list