[Haskell-cafe] Please add a method for optimized concat to the Semigroup class
ekmett at gmail.com
Wed May 4 14:25:12 CEST 2011
On Wed, May 4, 2011 at 7:40 AM, John Lato <jwlato at gmail.com> wrote:
> From: Edward Kmett <ekmett at gmail.com>
>> On Tue, May 3, 2011 at 3:43 PM, Yitzchak Gale <gale at sefer.org> wrote:
>> > 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.
>> Sold! (modulo the semantic considerations above)
> Somewhat academic, but would there be a case for implementing sconcat in
> terms of Foldable (or similar)?
There is a Foldable1 in semigroupoids. I could move it into the semigroups
package, but at the consequence that Data.Semigroup.Foldable wouldn't look
like Data.Foldable API-wise, since the Semigroupoid package is what
introduces Apply and Bind, giving you an Applicative sans pure and a Monad
sans return, which are needed to make most of the analogues to the Foldable
So to do so, I'd need to move those into this package. This is not entirely
implausible, if somewhat inconvenient from the perspective of keeping the
semigroups package tiny. The default definition would wind up being
class Semigroup a where
(<>) :: a -> a -> a
sconcat :: Foldable1 f => f a -> a
sconcat = fold1
class Foldable f => Foldable1 f where
fold1 :: Semigroup a => f a -> a
fold1 = foldMap1 id
foldMap1 :: Semigroup a => (b -> a) -> f b -> a
foldMap1 = ...
foldr1 :: ...
foldl1 :: ...
choosing sconcat = fold1 by default seems pretty much optimal under those
conditions, saying that if your Semigroup doesn't have an optimized fold,
you might as well let the container figure out what to do instead.
If we do that though, I'm hard pressed to find anything better to specialize
to for most semigroups, which is what I was saying earlier to Yitzchak, and
why I had omitted sconcat from the original API.
I suppose you might exploit foldl, foldr, foldl' or foldr' instead to play a
bit with how your traversal associates by default, or to use a different,
more efficient intermediate state though.
However, I am somewhat worried that with the type of the container
abstracted that it probably won't receive the same love from the strictness
One other annoying implementation consequence is that it would make the
Data.Semigroup and Data.Semigroup.Foldable modules rather hopelessly
entangled, so that I'd have to factor out the classes into a common
Internals module, then re-export the appropriate fragments through separate
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the Haskell-Cafe