Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing combinators for creating and consuming Fold1, and IndexedFold1 's #1015

Open
noinia opened this issue Dec 17, 2022 · 4 comments · May be fixed by #1057
Open

Missing combinators for creating and consuming Fold1, and IndexedFold1 's #1015

noinia opened this issue Dec 17, 2022 · 4 comments · May be fixed by #1057

Comments

@noinia
Copy link

noinia commented Dec 17, 2022

When working with Fold1 and/or IndexedFold1's it would be nice to have functions such as 'folding1' and 'ifolding1' to build the appropriate non-empty folds, and an indexed version of 'toNonEmptyOf' to consume them. In particular, I would suggest the following implementations:

-- | construct a Fold1 from a function that produces a Foldable1
folding1         :: Foldable1 f => (s -> f a) -> Fold1 s a
folding1 sfa agb = phantom . traverse1_ agb . sfa
{-# INLINE folding1 #-}

-- | Version of ifolding to build an 'IndexedFold1'
ifolding1       :: (Foldable1 f, Indexable i p, Contravariant g, Apply g)
                => (s -> f (i, a)) -> Over p g s t a b
ifolding1 sfa f = phantom . traverse1_ (phantom . uncurry (indexed f)) . sfa
{-# INLINE ifolding1 #-}

-- | indexed version of 'toNonEmptyOf'
itoNonEmptyOf   :: IndexedGetting i (NonEmptyDList (i,a)) s a -> s -> NonEmpty (i,a)
itoNonEmptyOf l = flip getNonEmptyDList [] . ifoldMapOf l (\i a -> NonEmptyDList $ ((i,a) :|))
{-# INLINE itoNonEmptyOf #-}

The implementations of folding1 and ifolding1 are almost identical to folding and ifolding (but with a different typeclass constraint). The implementation of iToNonEmptyOf was adapted from toNonEmptyOf

@gnull
Copy link

gnull commented Jan 25, 2024

Would you @ekmett accept a PR for this?

@ekmett
Copy link
Owner

ekmett commented Jan 25, 2024

Given we export Fold1, I think it'd be reasonable to supply basic combinators for working with them like this. So yes, I would accept a PR.

@noinia
Copy link
Author

noinia commented Feb 24, 2024

I've made a PR that implements the above functions. In a similar vain as this issue, I'm missing maximum1ByOf, minimum1ByOf analogues of maximumByOf and minimumByOf. If you are open to adding combinators like that as well, I can open another PR.

@ekmett
Copy link
Owner

ekmett commented Feb 24, 2024

With those additions, I'm wondering if we shouldn't exile these (along with the combinators in the PR above) to a Control.Lens.Fold1 or Control.Lens.Semigroup.Fold as they do require more "power" than that of a Fold, so they seem to be somewhat misplaced. Then we can decide if it makes sense to design that module for named import or regular, and whether these names should be in the default export set for lens.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants