Migrating from Lifted Transformers
Chimney’s Lifted Transformers (deprecated) were historically the first experimental attempt to express transformations that may potentially fail. Despite their great expressiveness, they were lacking several basic features and had a few design flaws that make them unattractive/difficult for wider adoption.
Important
In case you are using lifted transformers, we strongly recommend migration to Partial transformers.
Design differences
Let’s have a look at type signatures of both lifted and partial transformers.
package io.scalaland.chimney
// lifted transformer
trait TransformerF[F[+_], From, To] {
def transform(src: From): F[To]
}
// partial transformer
import io.scalaland.chimney.partial
trait PartialTransformer[From, To] {
def transform(src: From, failFast: Boolean): partial.Result[To]
}
Lifted transformers provided abstraction over the target transformation type container (
F[+_]), while partial transformers fix resulting type to built-inpartial.Result[_]as a consequence of this abstraction, lifted transformers required a type class instance (
TransformerFSupport) in scope for every specificF[_+]usedpartial transformers rely on built-in behavior and provide convenience methods to convert between more familiar data types (
Option,Either, etc.)abstraction over the resulting container type in lifted transformer allowed for having custom error types; this is not easily possible with partial transformer, which focuses on few most common error types
Partial transformer has built-in support for fail fast (short circuiting) semantics by passing
failFastboolean parameter, while in lifted transformers it was barely possible (only by providing supporting type class that had such a fixed behavior)Error path support in lifted transformers required providing another type class instance (
TransformerFErrorPathSupport) for your errors collection type, while in partial transformers it is a built-in feature
Migrating your code
In order to migrate your code from lifted transformers to partial transformers, you may take the following steps.
Replace all the occurrences of
TransformerFtype withPartialTransformerand remove the first type argument (F[_]) which is not used for partial transformers.For your transformations find corresponding DSL methods. Their name usually differ on suffix, for example:
replace
withFieldConstFwithwithFieldConstPartialreplace
withFieldComputedFwithwithFieldComputedPartialetc.
Adjust the types passed to the customization methods. In lifted transformers they were expecting values of your custom type
F[T], while in partial transformers they work withpartial.Result[T]. See thepartial.Resultcompanion object for ways of constructing success and failure instances, for example:Result.fromValueResult.fromOptionResult.fromEitherResult.fromTryand so on…
Resulting type of a call to
.transformis also apartial.Result[T]. If you don’t want to work withpartial.Resultdirectly, figure out ways how to convert it to other, more familiar data structures. Some of the ways may include:result.asOptionresult.asEitherresult.asErrorPathMessagesother data structures using Cats integration
See also our test suites for lifted transformers and partial transformers to get an idea how similar behavior might be implemented using both features.