magnolia1.magnolia.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of magnolia_native0.5_3 Show documentation
Show all versions of magnolia_native0.5_3 Show documentation
Fast, easy and transparent typeclass derivation for Scala 3
The newest version!
package magnolia1
import scala.deriving.Mirror
trait CommonDerivation[TypeClass[_]]:
type Typeclass[T] = TypeClass[T]
/** Must be implemented by the user of Magnolia to construct a typeclass for case class `T` using the provided type info. E.g. if we are
* deriving `Show[T]` typeclasses, and `T` is a case class `Foo(...)`, we need to constuct `Show[Foo]`.
*
* This method is called 'join' because typically it will _join_ together the typeclasses for all the parameters of the case class, into
* a single typeclass for the case class itself. The field [[CaseClass.params]] can provide useful information for doing this.
*
* @param caseClass
* information about the case class `T`, its parameters, and _their_ typeclasses
*/
def join[T](caseClass: CaseClass[Typeclass, T]): Typeclass[T]
inline def derivedMirrorProduct[A](
product: Mirror.ProductOf[A]
): Typeclass[A] = join(CaseClassDerivation.fromMirror(product))
inline def getParams__[T, Labels <: Tuple, Params <: Tuple](
annotations: Map[String, List[Any]],
inheritedAnnotations: Map[String, List[Any]],
typeAnnotations: Map[String, List[Any]],
repeated: Map[String, Boolean],
defaults: Map[String, Option[() => Any]],
idx: Int = 0
): List[CaseClass.Param[Typeclass, T]] = CaseClassDerivation.paramsFromMaps(
annotations,
inheritedAnnotations,
typeAnnotations,
repeated,
defaults
)
// for backward compatibility with v1.1.1
inline def getParams_[T, Labels <: Tuple, Params <: Tuple](
annotations: Map[String, List[Any]],
inheritedAnnotations: Map[String, List[Any]],
typeAnnotations: Map[String, List[Any]],
repeated: Map[String, Boolean],
idx: Int = 0
): List[CaseClass.Param[Typeclass, T]] =
getParams__(annotations, Map.empty, typeAnnotations, repeated, Map(), idx)
// for backward compatibility with v1.0.0
inline def getParams[T, Labels <: Tuple, Params <: Tuple](
annotations: Map[String, List[Any]],
typeAnnotations: Map[String, List[Any]],
repeated: Map[String, Boolean],
idx: Int = 0
): List[CaseClass.Param[Typeclass, T]] =
getParams__(annotations, Map.empty, typeAnnotations, repeated, Map(), idx)
end CommonDerivation
trait ProductDerivation[TypeClass[_]] extends CommonDerivation[TypeClass]:
inline def derivedMirror[A](using mirror: Mirror.Of[A]): Typeclass[A] =
inline mirror match
case product: Mirror.ProductOf[A] => derivedMirrorProduct[A](product)
inline given derived[A](using Mirror.Of[A]): Typeclass[A] = derivedMirror[A]
end ProductDerivation
trait Derivation[TypeClass[_]] extends CommonDerivation[TypeClass] with SealedTraitDerivation:
/** This must be implemented by the user of Magnolia to construct a Typeclass for 'T', where 'T' is a Sealed Trait or Scala 3 Enum, using
* the provided type info. E.g. if we are deriving 'Show[T]' typeclasses, and T is an enum 'Suit' (eg with values Diamonds, Clubs, etc),
* we need to constuct 'Show[Suit]'.
*
* This method is called 'split' because it will ''split'' the different possible types of the SealedTrait, and handle each one to
* finally produce a typeclass capable of handling any possible subtype of the trait.
*
* A useful function for implementing this method is [[SealedTrait#choose]], which can take a value instance and provide information on
* the specific subtype of the sealedTrait which that value is.
*/
def split[T](sealedTrait: SealedTrait[Typeclass, T]): Typeclass[T]
transparent inline def subtypes[T, SubtypeTuple <: Tuple](
m: Mirror.SumOf[T],
idx: Int = 0 // no longer used, kept for bincompat
): List[SealedTrait.Subtype[Typeclass, T, _]] =
subtypesFromMirror[T, SubtypeTuple](m, idx)
inline def derivedMirrorSum[A](sum: Mirror.SumOf[A]): Typeclass[A] =
split(sealedTraitFromMirror(sum))
inline def derivedMirror[A](using mirror: Mirror.Of[A]): Typeclass[A] =
inline mirror match
case sum: Mirror.SumOf[A] => derivedMirrorSum[A](sum)
case product: Mirror.ProductOf[A] => derivedMirrorProduct[A](product)
inline def derived[A](using Mirror.Of[A]): Typeclass[A] = derivedMirror[A]
protected override inline def deriveSubtype[s](
m: Mirror.Of[s]
): Typeclass[s] = derivedMirror[s](using m)
end Derivation
trait AutoDerivation[TypeClass[_]] extends Derivation[TypeClass]:
inline given autoDerived[A](using Mirror.Of[A]): TypeClass[A] = derived