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")))
// )
// )
// )