GithubHelp home page GithubHelp logo

Comments (8)

joroKr21 avatar joroKr21 commented on August 17, 2024 1

@mrdziuban I drafted an example for Eq: #626 - Let me know what do you think?

from kittens.

joroKr21 avatar joroKr21 commented on August 17, 2024

That's rather a deliberate design choice. Changing it at this point is not an option as it would be really disruptive. What we can consider is adding one more flavour of derivation with these semantics. However that can be as complex as reimplementing everything.

Also keep in mind that for sealed traits (and enums in Scala 3) usually you do want to to derive recursively for all cases. Otherwise it becomes very tedious to do this for every single case manually.

from kittens.

mrdziuban avatar mrdziuban commented on August 17, 2024

A separate type of derivation would work for me, but I really do think the existing behavior is counterintuitive and is likely to bite other users.

Regarding sealed traits, my ideal is that semiauto derivation would handle case objects automatically, without needing to derive for them manually, but that it would not automatically handle case classes. This is how semiauto derivation works in circe for scala 2 and I've always found it to be a reasonable approach that doesn't add a lot of boilerplate.

from kittens.

joroKr21 avatar joroKr21 commented on August 17, 2024

A separate type of derivation would work for me, but I really do think the existing behavior is counterintuitive and is likely to bite other users.

I think a change of behaviour would be more confusing than a new feature.

BTW, can you come up with a good name for it? 😄 I think that might be the hardest part actually.
I'm thinking about maybe adding an implicit parameter to configure this behaviour which is enabled by default in the current semiauto. But we would need a new import and I'm struggling to come up with a name for it.

from kittens.

mrdziuban avatar mrdziuban commented on August 17, 2024

I think a change of behaviour would be more confusing than a new feature.

I get where you're coming from, but it could be a new major release with the change called out. Plus anyone who blindly upgrades would only see new compile errors, rather than transparent changes in runtime behavior, so they would learn about the change and be able to decide what to do. That said, I'm still open to a whole new approach to derivation if that's what you think is best.

I'm thinking about maybe adding an implicit parameter to configure this behaviour which is enabled by default in the current semiauto.

Do you mean that enabling auto-derivation for nested types would require this new implicit/import? Or that disabling it would require the implicit?

Either way, my opinion is that a completely separate entrypoint for each behavior would be a better approach. People (including me 🙂) are bound to forget the import and unintentionally opt in or out of the behavior. Plus it'll be a lot easier to see and understand which style of derivation is being used at each call site -- you just look at which method is being called, rather than having to scroll to the top of the file to inspect the imports.

As far as a name goes, I don't have a great idea either...maybe something explicit like semiauto.derivedNoAutoRecursion (which is what I did in my PR to circe for the similar issue) or something less verbose but more opaque like semiauto.derivedOne or semisemiauto.derived?

from kittens.

joroKr21 avatar joroKr21 commented on August 17, 2024

I get where you're coming from, but it could be a new major release with the change called out. Plus anyone who blindly upgrades would only see new compile errors, rather than transparent changes in runtime behavior, so they would learn about the change and be able to decide what to do.

That is if we assume that there is one correct behaviour. Which I disagree with, both approaches are valid and ideally we should offer both.

Do you mean that enabling auto-derivation for nested types would require this new implicit/import? Or that disabling it would require the implicit?

Not necessarily a new import. The mechanism to implement it might be different from the API. At least in Scala 3, we can add an inline import without a problem. For Scala 2, I need to think about it more.

Either way, my opinion is that a completely separate entrypoint for each behavior would be a better approach.

Yes, I meant a different entry point but it still needs a name.

Here is how semiauto looks in Scala 3. We need a different import name, not a different method name:

object semiauto:
  inline def eq[A]: Eq[A] = DerivedEq[A]
  inline def hash[A]: Hash[A] = DerivedHash[A]
  inline def empty[A]: Empty[A] = DerivedEmpty[A]
  inline def semigroup[A]: Semigroup[A] = DerivedSemigroup[A]
  inline def monoid[A]: Monoid[A] = DerivedMonoid[A]
  inline def order[A]: Order[A] = DerivedOrder[A]
  inline def commutativeSemigroup[A]: CommutativeSemigroup[A] = DerivedCommutativeSemigroup[A]
  inline def commutativeMonoid[A]: CommutativeMonoid[A] = DerivedCommutativeMonoid[A]
  inline def applicative[F[_]]: Applicative[F] = DerivedApplicative[F]
  inline def apply[F[_]]: Apply[F] = DerivedApply[F]
  inline def emptyK[F[_]]: EmptyK[F] = DerivedEmptyK[F]
  inline def pure[F[_]]: Pure[F] = DerivedPure[F]
  inline def foldable[F[_]]: Foldable[F] = DerivedFoldable[F]
  inline def functor[F[_]]: Functor[F] = DerivedFunctor[F]
  inline def reducible[F[_]]: Reducible[F] = DerivedReducible[F]
  inline def traverse[F[_]]: Traverse[F] = DerivedTraverse[F]
  inline def nonEmptyTraverse[F[_]]: NonEmptyTraverse[F] = DerivedNonEmptyTraverse[F]
  inline def show[A]: Show[A] = DerivedShow[A]
  inline def semigroupK[F[_]]: SemigroupK[F] = DerivedSemigroupK[F]
  inline def monoidK[F[_]]: MonoidK[F] = DerivedMonoidK[F]
  inline def contravariant[F[_]]: Contravariant[F] = DerivedContravariant[F]
  inline def invariant[F[_]]: Invariant[F] = DerivedInvariant[F]
  inline def partialOrder[A]: PartialOrder[A] = DerivedPartialOrder[A]
  inline def showPretty[A]: ShowPretty[A] = DerivedShowPretty[A]

from kittens.

joroKr21 avatar joroKr21 commented on August 17, 2024

I don't know what I would call it - perhaps strict?
Then we have the derives enrichment which can go in cats.derived.strict and the explicit methods can go in cats.derived.strict.semiauto or cats.derived.semiauto.strict.

from kittens.

mrdziuban avatar mrdziuban commented on August 17, 2024

Thanks for explaining, I understand now. strict.semiauto or semiauto.strict sounds reasonable to me, let me know if there's any way I can help!

from kittens.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.