-
-
Notifications
You must be signed in to change notification settings - Fork 101
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
Lifted transformers #146
Lifted transformers #146
Conversation
chimney/src/main/scala/io/scalaland/chimney/dsl/TransformerDefinition.scala
Outdated
Show resolved
Hide resolved
chimney/src/main/scala/io/scalaland/chimney/dsl/TransformerInto.scala
Outdated
Show resolved
Hide resolved
chimney/src/main/scala/io/scalaland/chimney/TransformerFSupport.scala
Outdated
Show resolved
Hide resolved
Codecov Report
@@ Coverage Diff @@
## master #146 +/- ##
==========================================
+ Coverage 95.06% 99.35% +4.29%
==========================================
Files 13 20 +7
Lines 527 623 +96
Branches 79 52 -27
==========================================
+ Hits 501 619 +118
+ Misses 26 4 -22
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First round of review
chimney/src/main/scala/io/scalaland/chimney/TransformerFSupport.scala
Outdated
Show resolved
Hide resolved
chimney/src/main/scala/io/scalaland/chimney/dsl/TransformerDefinition.scala
Outdated
Show resolved
Hide resolved
chimney/src/main/scala/io/scalaland/chimney/dsl/TransformerFDefinition.scala
Outdated
Show resolved
Hide resolved
chimney/src/main/scala/io/scalaland/chimney/internal/macros/DslWhiteboxMacros.scala
Outdated
Show resolved
Hide resolved
30b2ca5
to
bc07c0d
Compare
Now I think almost all of the bullets from TODO list was addressed. There is comprehensive test suite which should cover all the cases in the context of lifted transformers. I think it's a good moment to take another round of review. cc: @ulanzetz, @Phill101, @MateuszKubuszok Next steps would be:
|
package object cats { | ||
|
||
implicit def TransformerFValidatedSupport[EE: Semigroup]: TransformerFSupport[Validated[EE, +*]] = | ||
new TransformerFSupport[Validated[EE, +*]] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add cats.data.Ior for semigroup A instance too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like a good idea 👍
But I'm struggling with reasonable semantics of
def product[A, B](fa: Ior[EE, A], fb: => Ior[EE, B]): Ior[EE, (A, B)]
for few cases:
- when
fa = Left(e)
andfb = Right(b)
- we cannot haveIor.Both
, as we can't construct right pair ((A, B)
), since we only haveB
;Ior.Left
is the only result we can have here - when
fa = Left(e1)
andfb = Both(e2, b)
- we can combinee1
ande2
using Semigroup instance, but also we cannot haveIor.Both
as a result
It also includes symmetrical cases.
I'm not really familiar with using Ior
, but I'm afraid that product
can't be implemented with substantial information loss. The question is if such semantics makes sense at all?
chimney/src/main/scala/io/scalaland/chimney/internal/utils/EitherUtils.scala
Show resolved
Hide resolved
chimney/src/main/scala/io/scalaland/chimney/internal/utils/EitherUtils.scala
Show resolved
Hide resolved
257f521
to
69ec21a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't found any issues with the code
* | ||
* In order to create lifted transformation from `A` to `F[B]`, | ||
* we need these few operations to be implemented for specific `F` | ||
* wrapper type. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Link to docs showing why using Iterator
is not a problem if anyone had problem with that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this explained enough in a scaladoc of traverse
?
initial design of lifted transformers - separate type class (LiftedTransformer) that works with F[_] - LiftedTransformerSupport type class that code is generated against which decides on composition semantics of resulting F[_] - parallel hierarchy of Lifted-{TransformerInto/TransformerDefinition} (not complete yet) - few test cases working with Option and Either (not passing yet) better error message on withFieldComputedLifted when types don't match renaming: LiftedTransformer -> TransformerF stronger type signatures for whitebox macro impl backed dsl operations code cosmetics LiftedDslSpec -> DslFSpec connect dsl with macro stuff code formatting first, always-succeeding test for TransformerF passes - added pure: A => F[A] to TransformerFSupport - use pure to wrap target transformer tree first bunch of tests on TransformerF passes code formatting simplify generated tuple extractor pattern: untyped bind is ok extract TypeOps.applyTypeArg for type argument application use kind-projector plugin generalized TransformerFEitherErrorAccumulatingSupport to support any collection of errors as long as we have implicit Factory for creating Builders code formatting renaming trying to pass recursive TransformerF test - wip reworking case class mapping resolution and recursive transformer body expansion (wip) reworking case class expansion (wip) comment next steps still wip new case class mapping algorithm works with all TransformerF tests! - there's one test case that doesn't work (IssuesSpec -> #121) fix error messages in recursive cases code formatting backport 2.13-only either combinators to EitherUtils towards 2.11/2.12 support work arounds for type inference so that DslFSpec pass on 2.11 too code formatting refactor: extract mkNewJavaBean refactor: extract mkNewJavaBean/mkNewClass to TargetConstructorMacros - extract Model trait rewrite expandDestinationTuple using new mapping routines code formatting use new mapping algorithm in tuples and java beans destinations use &&& in scala-collection-compat dependency get rid of unused implicit relax `traversable` type bound to IterableOnce bring back -Xfatal-warnings on 2.12+ generalize traverse signature and implementations to support different input/output collection types use -language:higherKinds compiler flag instead of scala.language.higherKinds imports more test cases for 3-arg wrapped transformation TransformerF support for value classes code formatting figure out transformation under Option figure out transformation under Option remove redundant case in expandOptions refactor more detailed test cases for collections add more collection test cases (array as target) refactor collection transformation use .fold on Either instead of pattern matching bugfix wrong subtype test refactor expandEithers expandEithers working with lifted transformers code formatting lifted subtype transformation eliminate expandMaps case keeping the same functionality - Maps are iterables, where inner type is tuple - we can re-use tuple expansion for expanding inner transformer - perhaps added well defined collection -> map and map -> collection conversions for free (but need to test it more extensively) - all current tests pass remove dead code add test cases: - between iterables and maps - between arrays and maps tests for wrapped maps added few TODO comments lifted transformers for expandTargetWrappedInOption - refactored to be expressed using expandOptions lifted transformers for expandSourceWrappedInOption refactor expandSealedClasses lifted transformer support for expandSealedClasses - new DSL operator: withCoproductInstanceF - changed rules of expanding sealed classes (so that instances provided by DSL has priority over automatic derivation) - need to require covariant wrapper type F (due to convenience of withCoproductInstanceF) - number of test cases for lifted transformers, verifying also support for GADTs code formatting changed order of type parameters in `intoF` - F comes first to be consistent with `transformIntoF` docs wip extract ConfigDsl to avoid code/docs duplication code formatting complete operations in both pure and lifted dsl - scaladocs - simplified implementation, removed DslWhiteboxMacros scaladocs for dsl scaladocs for TransformerFSupport refactor fresh term names not measure coverage on impossible cases materialize TransformerFSupport before macro expansion fix term name prefix ("left" -> "right") can't eliminate WrapperType refactor mkWrappedTransformerBody - added special implementations for argless and unary cases code formatting removed misleading return types from scaladocs refactor TransformerCfg type constructors rename: combine to product in TransformerFSupport cats module with TransformerFSupport instance for cats.data.Validated refactor in DslFSpec tests for cats Validated module increasing test coverage
365e686
to
29b10a7
Compare
- as the function doesn't always produce wrapped tree
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Far from being chimney expert but it looks good to me 🚀 🎉
…onflicts (#151) * Add tests for enforcing explicit resolution of transformer implicit conflicts * hacky utils for refineTransformerDefinition that work on 2.11-2.13 * fixed test cases to compile * code formatting * keep corespondence between value-level TransformerDefinition(F) instances/overrides and its type-level configuration - so far the config was parsed in wrong way so that if someone provided withFieldXXX twice for the same field, it could end up with generating unsound code * enhance recursive wrapped transformer resolution algorithm - first look for bot pure and wrapped implicits - if one of them was found, use it - if both of them were found, report ambiguity error - if no implicit was found try deriving and instance - first try to derive pure instance - if pure instance cannot be derived, try deriving lifted instance * docs for improved lifted transformer derivation Co-authored-by: Piotr Krzemiński <pio.krzeminski@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM - let's keep it open on case someone would found an issue, but IMHO it's a complete feature
I cant go through code right now but I tried to think about cases in which this feature interacts with my quite long experience with using chimney in production. Everything else looks good! I'm quite astonished by the amount of work put in this. Great job! |
@Krever this PR actually keeps |
@Krever also you can define something like this
and make your option unwrapping safe |
This PR is implementation of #118 approached in a bit different way to alternative #145 proposed by @ulanzetz.
Differences highlight:
Transformer
type class, along withTransformerF
; the macro is generalized to be able to derive any transformer (pure or wrapped) as the derivation structure and rules seems to be the same; TransformerF and cats.data.Validated support #145 removesTransformer
and usesTransformerF[Id, From, To]
for pure transformersF[_]
; in this PR there isTransformerFSupport
, in TransformerF and cats.data.Validated support #145 there isTransformationContext
; there are minor differences in signatures (and naming), but they are mostly do the samewithFieldConst
/withFieldComputed
) with wrapped ones (withFieldConstF
/withFieldComputedF
) in such a way that pure ones doesn't need to be boxed usingTransformerFSupport.pure
; as far as I understand, TransformerF and cats.data.Validated support #145 always wraps inTransformationContext.pure
, even in caseF = Id
Option[*]
andEither[M[E], *]
After a brief look, both solutions should provide source compatibility, however in this PR several compile error messages may have changed due to refactor of mapping algorithm.
TODO list includes:
TransformerFDefinition
andTransformerFInto
I believe we can pick best of both (this and #145) to the final release.
Any feedback is highly appreciated.