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

Add flip foldMap #87

Open
ysangkok opened this issue Aug 20, 2021 · 5 comments
Open

Add flip foldMap #87

ysangkok opened this issue Aug 20, 2021 · 5 comments

Comments

@ysangkok
Copy link
Contributor

flipped foldMap: (Foldable t, Monoid c) => t a -> (a -> c) -> c

It is similar to whenJust, but more pure, while whenJust is inherently effectful since it returns unit.

It can be used e.g. in the HTML AST of an Elm-style render function, when you want to optionally render something. In that case you'd wanna render nothing at all (mempty) when you get a Nothing.

In that case, the instantiation would be Maybe a -> (a -> HTML) -> HTML. If you had mbMyNumber, you could do flippedFoldMap mbMyNumber renderNumber instead of case mbMyNumber of Nothing -> mempty; Just x -> renderNumber x.

I am posting the issue here because I think the function is very general, and I was expecting whenJust to do just this. So maybe other people will have the same suspicion, and it would make sense to have this function next to the existing whenJust. The problem is, I don't know what to call this flipped foldMap.

On IRC, dsal made me aware that whenJust = flip traverse_. Maybe the fact that whenJust could be more general than it is, means that the general version should also be available? It seems weird to argue that flip traverse_ should be specialized but flip foldMap shouldn't. Either way, to have this added, we'd need a name, and the best name I can think of is whenJust, but it is taken. Would love to hear whether you think this function belongs here or not, and what it should be called.

ghci> :t flip traverse_ :: Monad m => Maybe a -> (a -> m ()) -> m ()
flip traverse_ :: Monad m => Maybe a -> (a -> m ()) -> m ()
  :: Monad m => Maybe a -> (a -> m ()) -> m ()

Thanks for your library, it has been very useful.

@ndmitchell
Copy link
Owner

It seems to be a pattern that these functions come in flipped and non-flipped versions, so it doesn't seem unreasonable. I think the question of what it should be named is probably key. If the name seems to obviously indicate what it does, then it seems good to add. If the name isn't obvious, then it would require people to look up, and probably makes code using it harder to understand. I don't have any good ideas for a name, but I think that's the key question.

@ysangkok
Copy link
Contributor Author

What about mapMconcat or mapSummarize or mapSummarise or just plain summarize? @cdsmith has referred to mconcat as summarizing: https://cdsmithus.medium.com/monoids-are-composable-list-summarizers-77d2baf23ffc

@cdsmith
Copy link

cdsmith commented Feb 10, 2022

While I did write that article, I don't think the word "summarize" is sufficiently precise to make a good name. Here are some candidates off the top of my head:

  • foldEach - this is probably my favorite name in general
  • foldFor - because sometimes for is used to mean flip map, though lately it's been more often used for flip traverse instead. A variant is foldOver, since we talk about folding over a list.
  • mapFold - I'm not a fan, but it's a sort of flip of foldMap.

@endgame
Copy link

endgame commented Feb 10, 2022

I stand by my suggestion of paMdolf, but I think that in the age of -XBlockArguments (GHC >=8.6.1) the need for a distinct function is much lower: Just 3 & foldMap \m -> Sum (m * 2) is actually pretty nice.

@ndmitchell
Copy link
Owner

Agreed summarise doesn't seem right, since a function called summarise could do almost anything. I'm ok with foldEach/foldFor/mapFold, but have no strong preference on which, or if the function is useful enough with block arguments etc.

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

No branches or pull requests

4 participants