Skip to content

Commit

Permalink
Switch to using Scala 3.5-style for Contrastable
Browse files Browse the repository at this point in the history
  • Loading branch information
propensive committed Jun 5, 2024
1 parent 13f074c commit 693d82c
Showing 1 changed file with 19 additions and 17 deletions.
36 changes: 19 additions & 17 deletions src/core/comparison.scala
Original file line number Diff line number Diff line change
Expand Up @@ -88,44 +88,46 @@ object Similarity:
trait Similarity[-ValueType]:
def similar(a: ValueType, b: ValueType): Boolean

trait Contrastable[-ValueType]:
def apply(a: ValueType, b: ValueType): Semblance
trait Contrastable:
type Self
def apply(left: Self, right: Self): Semblance

extension [ValueType](left: ValueType)
inline def contrastWith(right: ValueType): Semblance = compiletime.summonFrom:
case contrastable: Contrastable[ValueType] => contrastable(left, right)
case _ => Contrastable.general(left, right)
case contrastable: (ValueType is Contrastable) => contrastable(left, right)
case _ => Contrastable.general(left, right)

object Contrastable extends Derivation[Contrastable]:
def nothing[ValueType]: Contrastable[ValueType] = (left, right) => Semblance.Identical(left.debug)
object Contrastable extends Derivation[[ValueType] =>> ValueType is Contrastable]:
def nothing[ValueType]: ValueType is Contrastable = (left, right) =>
Semblance.Identical(left.debug)

given int: Contrastable[Int] = (left, right) =>
given Int is Contrastable as int = (left, right) =>
if left == right then Semblance.Identical(left.show)
else Semblance.Different(left.show, right.show, t"${math.abs(right - left)}")

given double: Contrastable[Double] = (left, right) =>
given Double is Contrastable = (left, right) =>
given Decimalizer = Decimalizer(3)
if left == right then Semblance.Identical(left.show)
else
val size = 100*(right - left)/left
val sizeText = if size.isFinite then t"${if size > 0 then t"+" else t""}$size%" else t""
Semblance.Different(left.show, right.show, sizeText)

inline def general[ValueType]: Contrastable[ValueType] = (left, right) =>
inline def general[ValueType]: ValueType is Contrastable = (left, right) =>
if left == right then Semblance.Identical(left.debug) else Semblance.Different(left.debug, right.debug)

inline given Contrastable[Exception]:
inline given Exception is Contrastable:
def apply(left: Exception, right: Exception): Semblance =
val leftMsg = Option(left.getMessage).fold(t"null")(_.nn.debug)
val rightMsg = Option(right.getMessage).fold(t"null")(_.nn.debug)

if left.getClass == right.getClass && leftMsg == rightMsg then Semblance.Identical(leftMsg)
else Semblance.Different(leftMsg, rightMsg)

given Contrastable[Char] = (left, right) =>
given Char is Contrastable = (left, right) =>
if left == right then Semblance.Identical(left.show) else Semblance.Different(left.show, right.show)

given Contrastable[Text] = (left, right) => compareSeq[Char](left.chars, right.chars, left, right)
given Text is Contrastable = (left, right) => compareSeq[Char](left.chars, right.chars, left, right)

inline def compareSeq[ValueType: Contrastable: Similarity]
(left: IndexedSeq[ValueType], right: IndexedSeq[ValueType], leftDebug: Text, rightDebug: Text)
Expand Down Expand Up @@ -154,26 +156,26 @@ object Contrastable extends Derivation[Contrastable]:
Semblance.Breakdown(comparison, leftDebug, rightDebug)


inline given [ValueType: Contrastable: Similarity] => Contrastable[IArray[ValueType]] as iarray:
inline given [ValueType: Contrastable: Similarity] => IArray[ValueType] is Contrastable as iarray:
def apply(left: IArray[ValueType], right: IArray[ValueType]): Semblance =
compareSeq[ValueType](left.to(IndexedSeq), right.to(IndexedSeq), left.debug, right.debug)

inline given [ValueType: Contrastable: Similarity] => Contrastable[List[ValueType]] as list:
inline given [ValueType: Contrastable: Similarity] => List[ValueType] is Contrastable as list:
def apply(left: List[ValueType], right: List[ValueType]): Semblance =
compareSeq[ValueType](left.to(IndexedSeq), right.to(IndexedSeq), left.debug, right.debug)

inline given [ValueType: Contrastable: Similarity] => Contrastable[Vector[ValueType]] as vector:
inline given [ValueType: Contrastable: Similarity] => Vector[ValueType] is Contrastable as vector:
def apply(left: Vector[ValueType], right: Vector[ValueType]): Semblance =
compareSeq[ValueType](left.to(IndexedSeq), right.to(IndexedSeq), left.debug, right.debug)

inline def join[DerivationType <: Product: ProductReflection]: Contrastable[DerivationType] = (left, right) =>
inline def join[DerivationType <: Product: ProductReflection]: DerivationType is Contrastable = (left, right) =>
val elements = fields(left, true): [FieldType] =>
leftParam =>
if leftParam == complement(right) then (label, Semblance.Identical(leftParam.debug))
else (label, context(leftParam, complement(right)))

Semblance.Breakdown(elements, left.debug, right.debug)

inline def split[DerivationType: SumReflection]: Contrastable[DerivationType] = (left, right) =>
inline def split[DerivationType: SumReflection]: DerivationType is Contrastable = (left, right) =>
variant(left): [VariantType <: DerivationType] =>
left => complement(right).let(left.contrastWith(_)).or(Semblance.Different(left.debug, right.debug))

0 comments on commit 693d82c

Please sign in to comment.