typelevel / cats

Lightweight, modular, and extensible library for functional programming.
https://typelevel.org/cats/
Other
5.25k stars 1.21k forks source link

IDEA: Auto generate Monoid[FunctionN] #4079

Open BalmungSan opened 2 years ago

BalmungSan commented 2 years ago

Currently cats provides a Monoid instance for Function0 & Function1: https://github.com/typelevel/cats/blob/main/kernel/src/main/scala/cats/kernel/instances/FunctionInstances.scala#L109 While these are very useful, it is not uncommon in Scala to have functions of higher arities like Function2. And, for all I can see, the implementation of such instances is just mechanical repetition.

Thus, this issue proposes the inclusion of the generation of all the repetitive code from trait Semigroup[Function2] until trait Monoid[Function22] extends Semigroup[Function22] AFAIK the only downside of such a proposal is the increase in the JAR size; but, personally, I think this is a good addition since not having those instances can be surprising and somehow inconsistent.

PS: I see that we also have Group instances for Function0 & Function1. However, I am unfamiliar with that typeclass and I am not totally sure if such instance is valid for higher arities and if the implementation is equally mechanical; for how the code looks like it seems so, thus I leave it open to also include those in the generator.

armanbilge commented 2 years ago

Re jar size, see https://github.com/typelevel/cats/pull/3871.

satorg commented 2 years ago

Yeah, jar size is a concern... I'm just thinking about a broader solution... I'm wondering, would it make sense to split cats-core into two parts: one is a minimalistic jar with all arities no more than 2 and the second is somewhat full-sized with all the remaining arities up to 22 (at least) and other size-costly goods? Would it work in general, wdyt?

johnynek commented 2 years ago

@satorg that would prevent them from being in implicit scope.

I think larger tuples are used rather frequently. I think FunctionN for N > 2 or 3 are very rarely used. So, I question the value of generating those and putting them on the classpath for everyone.

Also note the .tupled method on FunctionN.tupled which converts back to a Function1. I think that will likely be fine for most use cases and allow you to use the Function1 instances.

satorg commented 2 years ago

@johnynek one more import for that?

johnynek commented 2 years ago

yes, you would need another import.

satorg commented 2 years ago

I mean this is one of the things we could consider for future work. Most of libraries which depend on Cats don't need high-arity syntax (I guess). But sometimes it might be useful for business-level applications to support specific DTOs or pipelines. This is where such an extension module may come handy.

joroKr21 commented 2 years ago

This could also be part of Kittens: https://github.com/typelevel/kittens/blob/master/core/src/main/scala/cats/derived/function.scala