Transform into singleton types
MateuszKubuszok opened this issue · comments
Currently the only kinds support for singleton types we have are:
case object
s (Scala 2 & 3) and parametherlessenum
case
s (Scala 3)- filling
Unit
as constructor parameter/setter - filling
None
as constructor parameter/setter if we enable it with a flagenableOptionDefaultsToNone
We could allow transformting into/filling automatically any literal singleton types (e.g. String
s, Int
s, 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)
Transforming enums into underlying singletons i.e. via getValue could be extremely convenient, wondering are there any easy solutions to that right now?
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 AnyVal
s 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 AnyVal
s can be invented.
@MateuszKubuszok Oh that's right! Thanks for pointers. I'll try to play around for the local solution, nice.