<div dir="auto">That seems rather large to me, and some of those methods don't have much if any historical usage. I'd recommend starting with a slightly smaller class. It's always easier to add more later than to remove. My suggestion:<div dir="auto"><div dir="auto"><br></div><div dir="auto"> foldMap1 :: Semigroup m => (a -> m) -> t a -> m</div><div dir="auto"><br></div><div dir="auto"> foldMap1' :: Semigroup m => (a -> m) -> t a -> m</div><div dir="auto"><br></div><div dir="auto"> toNonEmpty :: t a -> NonEmpty a</div></div><br>The rest can be exported as functions, rather than methods, to begin with.<br><br><div class="gmail_quote" dir="auto"><div dir="ltr" class="gmail_attr">On Thu, Dec 10, 2020, 1:38 AM Reed Mullanix <<a href="mailto:reedmullanix@gmail.com">reedmullanix@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">With the recent discussion around the addition of 'intersection' to containers,<br>
I think it might be a good time to re-open the discussion surrounding adding<br>
'Foldable1' to base.<br>
<br>
For context, 'Foldable1' would be a subclass of 'Foldable' that abstracts<br>
folds over non-empty containers. Alternatively, it can be seen as a method<br>
of combining together the elements of a container using a semigroup.<br>
The contents of this class have been discussed previously (See [1,2]),<br>
and the version presented in this proposal is taken from [1].<br>
<br>
class Foldable t => Foldable1 t where<br>
{-# MINIMAL foldMap1 | foldr1map #-}<br>
<br>
fold1 :: Semigroup m => t m -> m<br>
<br>
-- the defining member, like foldMap but only asking for Semigroup<br>
foldMap1 :: Semigroup m => (a -> m) -> t a -> m<br>
<br>
-- strict foldMap1, cf foldMap'<br>
foldMap1' :: Semigroup m => (a -> m) -> t a -> m<br>
<br>
-- analogue of toList<br>
toNonEmpty :: t a -> NonEmpty a<br>
<br>
-- left&right, strict&non-strict folds<br>
foldr1 :: (a -> a -> a) -> t a -> a<br>
foldr1' :: (a -> a -> a) -> t a -> a<br>
foldl1 :: (a -> a -> a) -> t a -> a<br>
foldl1' :: (a -> a -> a) -> t a -> a<br>
<br>
-- these can have efficient implementation for NonEmptySet<br>
maximum1 :: Ord a => t a -> a<br>
minimum1 :: Ord a => t a -> a<br>
<br>
-- head1 have efficient implementation for NonEmpty and Tree<br>
-- last1 for symmetry<br>
head1 :: t a -> a<br>
last1 :: t a -> a<br>
<br>
-- fold variants with premap.<br>
-- Without this map, we cannot implement foldl using foldr etc.<br>
foldrMap1 :: (a -> b) -> (b -> b -> b) -> t a -> b<br>
foldlMap1' :: (a -> b) -> (b -> b -> b) -> t a -> b<br>
foldlMap1 :: (a -> b) -> (b -> b -> b) -> t a -> b<br>
foldrMap1' :: (a -> b) -> (b -> b -> b) -> t a -> b<br>
<br>
<br>
This has a couple of benefits. On the practical side, we can provide<br>
total alternatives<br>
to existing partial functions (IE: 'foldr1' and friends). It also<br>
enables us to fold<br>
over containers using a semigroup instance, which comes up suprisingly often.<br>
<br>
Naming:<br>
--------------------------------------------------------------------------------<br>
Historically, the biggest source of controversy with this proposal has<br>
been over the<br>
name. The class currently exists in semigroupoids [3] under the name<br>
'Foldable1', though<br>
there was some discussion around renaming it to 'SemiFoldable' [4].<br>
However, if we keep<br>
the name unchanged, it makes the migration path nice and<br>
straightforward, and the possible<br>
name conflict with Data.Functor.Classes seems unlikely.<br>
<br>
Migration:<br>
--------------------------------------------------------------------------------<br>
If we decide to go with 'Foldable1' as the name, we should be able to<br>
perform this change with<br>
0 breakage.<br>
<br>
References:<br>
[1] <a href="https://mail.haskell.org/pipermail/libraries/2019-November/030059.html" rel="noreferrer noreferrer" target="_blank">https://mail.haskell.org/pipermail/libraries/2019-November/030059.html</a><br>
[2] <a href="https://gitlab.haskell.org/ghc/ghc/-/issues/13573" rel="noreferrer noreferrer" target="_blank">https://gitlab.haskell.org/ghc/ghc/-/issues/13573</a><br>
[3] <a href="https://hackage.haskell.org/package/semigroupoids-5.3.4/docs/Data-Semigroup-Foldable.html#t:Foldable1" rel="noreferrer noreferrer" target="_blank">https://hackage.haskell.org/package/semigroupoids-5.3.4/docs/Data-Semigroup-Foldable.html#t:Foldable1</a><br>
[4] <a href="https://github.com/ekmett/semigroupoids/issues/26" rel="noreferrer noreferrer" target="_blank">https://github.com/ekmett/semigroupoids/issues/26</a><br>
_______________________________________________<br>
Libraries mailing list<br>
<a href="mailto:Libraries@haskell.org" target="_blank" rel="noreferrer">Libraries@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries" rel="noreferrer noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries</a><br>
</blockquote></div></div>