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

Transform into singleton types #407

Closed
MateuszKubuszok opened this issue Oct 18, 2023 · 4 comments · Fixed by #559
Closed

Transform into singleton types #407

MateuszKubuszok opened this issue Oct 18, 2023 · 4 comments · Fixed by #559
Labels
dragons ahead Task which requires handwriting compiletime reflection for Scala2&3 and/or updating the architecture enhancement

Comments

@MateuszKubuszok
Copy link
Member

MateuszKubuszok commented Oct 18, 2023

Currently the only kinds support for singleton types we have are:

  • case objects (Scala 2 & 3) and parametherless enum cases (Scala 3)
  • filling Unit as constructor parameter/setter
  • filling None as constructor parameter/setter if we enable it with a flag enableOptionDefaultsToNone

We could allow transformting into/filling automatically any literal singleton types (e.g. Strings, Ints, etc literal types), since there is only 1 possible value that can be filled and we know exactly what's that value is.

Implementation would require:

  • creating new datatype in chimney-macro-commons
  • implementing macros (2.12/2.13/3) which would check that a type is singleton type
  • implementing new rule
  • testing
  • checking that this new rule is not colliding with existing rules (e.g. we explicitly ignore None in some methods, so perhaps we should ignore some singleton types or only support primitives literals: Unit/String/Int/numerical types)
@MateuszKubuszok MateuszKubuszok added enhancement dragons ahead Task which requires handwriting compiletime reflection for Scala2&3 and/or updating the architecture labels Oct 18, 2023
@pomadchin
Copy link

pomadchin commented May 16, 2024

Transforming enums into underlying singletons i.e. via getValue could be extremely convenient, wondering are there any easy solutions to that right now?

@MateuszKubuszok
Copy link
Member Author

I think something like that is cooked up by https://github.com/moia-oss/teleproto for PB enums.

I'd say that some particular cases could be user-extended by providing the right generic implicit. On Scala 3 that could be something with a Mirror I guess?

// maybe it would work, haven't checked
given unwrapSingleton[A <: Product, B](
  using Mirror.ProductOf[A] { type MirroredElemLabels = B *: EmptyTuple }
): Transformer[A, B] =
  (src: A) => src.productIterator.head.asInstanceOf[B]

given wrapSingleton[A <: Product, B](
  using m: Mirror.ProductOf[A] { type MirroredElemLabels = B *: EmptyTuple }
): Transformer[B, A] =
  (src: B) => m.fromTuple(src *: EmptyTuple)

If your enum extends some particular interface it can probably use it to extract the inner values.


Technically, macro are not far from being able to always unwrap/wrap values - there are rules that handle AnyVals for wrapping/unwrapping/rewrapping where we would only have to drop AnyVal check, but it haven't been done since:

  • it would be a change of behavior that nobody requested before
  • if any 1-value product is treated the same way as AnyVal I can imagine that in some cases like A1(B1(C1(D1(...)))) into A2(B2(C2(D2(...)))) testing every possibility (nesting or not) might explode the compilation time

so I was waiting till some sane way of saying what can be unwrapped besides AnyVals can be invented.

@pomadchin
Copy link

@MateuszKubuszok Oh that's right! Thanks for pointers. I'll try to play around for the local solution, nice.

@MateuszKubuszok MateuszKubuszok linked a pull request Jun 28, 2024 that will close this issue
14 tasks
@MateuszKubuszok
Copy link
Member Author

Released in 1.3.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dragons ahead Task which requires handwriting compiletime reflection for Scala2&3 and/or updating the architecture enhancement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants