chimney module
Import
import refined4s.modules.chimney.derivation.types.all.given
import refined4s.modules.chimney.derivation.*
Use Drived Instances for Pre-defined Types
To use Newtype, Refined and InlinedRefined with Chimney, you need to have type-class instances of Transformer[NewType, RawType] and PartialTransformer[RawType, NewType].
refined4s comes with them already.
import refined4s.modules.chimney.derivation.types.all.given
import refined4s.*
import refined4s.types.all.*
import io.scalaland.chimney
import io.scalaland.chimney.dsl.*
import refined4s.modules.chimney.derivation.types.all.given
final case class Person(name: NonEmptyString)
final case class User(name: NonEmptyString)
val person = Person(NonEmptyString("Wade Wilson"))
// person: Person = Person(name = "Wade Wilson")
person.intoPartial[User].transform
// res1: Result[User] = Value(value = User(name = "Wade Wilson"))
person.transformIntoPartial[User]
// res2: Result[User] = Value(value = User(name = "Wade Wilson"))
With Explicit Pre-defined Chimney Support
There are the following pre-defined traits to support chimney's Transformer and PartialTransformer
- refined4s.modules.chimney.derivation.ChimneyNewtype
- refined4s.modules.chimney.derivation.ChimneyRefined
import refined4s.*
import refined4s.modules.chimney.derivation.*
import io.scalaland.chimney.*
import io.scalaland.chimney.dsl.*
final case class Person(name: Person.Name)
object Person {
  type Name = Name.Type
  object Name extends Newtype[String], ChimneyNewtype[String]
}
final case class User(name: String)
final case class Member(name: Member.Name)
object Member {
  type Name = Name.Type
  object Name extends Newtype[String], ChimneyNewtype[String]
}
val person = Person(Person.Name("Wade Wilson"))
// person: Person = Person(name = "Wade Wilson")
Person.Name("Wade Wilson").into[String].transform
// res4: String = "Wade Wilson"
val deadpool = person.transformInto[User]
// deadpool: User = User(name = "Wade Wilson")
deadpool.transformInto[Person]
// res5: Person = Person(name = "Wade Wilson")
val member = person.transformInto[Member]
// member: Member = Member(name = "Wade Wilson")
member.transformInto[Person]
// res6: Person = Person(name = "Wade Wilson")
import refined4s.*
import refined4s.modules.chimney.derivation.*
import io.scalaland.chimney.*
import io.scalaland.chimney.dsl.*
final case class XMen(name: XMen.NotEmptyStr)
object XMen {
  type NotEmptyStr = NotEmptyStr.Type
  object NotEmptyStr extends Refined[String], ChimneyRefined[String] {
    inline def invalidReason(a: String): String = "non-empty String"
  
    inline def predicate(a: String): Boolean = a != ""
  }
}
final case class MarvelCharacter(name: String)
import refined4s.types.all.*
final case class Hero(name: Hero.Name)
object Hero {
  type Name = Name.Type
  object Name extends Newtype[NonEmptyString], ChimneyNewtype[NonEmptyString]
}
val logan = XMen(XMen.NotEmptyStr("James Howlett"))
// logan: XMen = XMen(name = "James Howlett")
val wolverine = logan.transformInto[MarvelCharacter]
// wolverine: MarvelCharacter = MarvelCharacter(name = "James Howlett")
wolverine.transformIntoPartial[XMen]
// res7: Result[XMen] = Value(value = XMen(name = "James Howlett"))
val hero = logan.transformIntoPartial[Hero]
// hero: Result[Hero] = Value(value = Hero(name = "James Howlett"))
With auto derivation
If you want to implicitly have Transformer and PartialTransformer type-class instances for your Newtype or Refined or InlinedRefined, you can use the refined4s.modules.chimney.derivation.generic.auto.
import cats.*
import refined4s.*
import refined4s.modules.chimney.derivation.generic.auto.given
import io.scalaland.chimney.*
import io.scalaland.chimney.dsl.*
type Name = Name.Type
object Name extends Newtype[String]
type NotEmptyStr = NotEmptyStr.Type
object NotEmptyStr extends Refined[String] {
  inline def invalidReason(a: String): String = "NonEmptyStr should be a non-empty String"
  inline def predicate(a: String): Boolean = a != ""
}
final case class Person(name: Name)
final case class User(name: String)
final case class AnotherUser(name: NotEmptyStr)
val person = Person(Name("Wade Wilson"))
// person: Person = Person(name = "Wade Wilson")
person.into[User].transform
// res9: User = User(name = "Wade Wilson")
val user = person.transformInto[User]
// user: User = User(name = "Wade Wilson")
user.transformIntoPartial[Person]
// res10: Result[Person] = Value(value = Person(name = "Wade Wilson"))
val anotherUser = person.transformIntoPartial[AnotherUser]
// anotherUser: Result[AnotherUser] = Value(
//   value = AnotherUser(name = "Wade Wilson")
// )
anotherUser.flatMap(_.transformIntoPartial[Person])
// res11: Result[Person] = Value(value = Person(name = "Wade Wilson"))
val personWithEmptyName = Person(Name(""))
// personWithEmptyName: Person = Person(name = "")
personWithEmptyName.transformInto[User]
// res12: User = User(name = "")
personWithEmptyName.transformIntoPartial[AnotherUser]
// res13: Result[AnotherUser] = Errors(
//   errors = NonEmptyErrorsChain(
//     Error(
//       message = StringMessage(
//         message = "Invalid value: []. NonEmptyStr should be a non-empty String"
//       ),
//       path = Path(elements = List(Accessor(name = "name")))
//     )
//   )
// )