diff --git a/core/shared/src/main/scala-3/org/typelevel/twiddles/Twiddles.scala b/core/shared/src/main/scala-3/org/typelevel/twiddles/Twiddles.scala index a035726..446e670 100644 --- a/core/shared/src/main/scala-3/org/typelevel/twiddles/Twiddles.scala +++ b/core/shared/src/main/scala-3/org/typelevel/twiddles/Twiddles.scala @@ -35,13 +35,18 @@ import cats.syntax.all._ trait TwiddleSyntax[F[_]]: - implicit def toTwiddleOpCons[B <: Tuple](fb: F[B]): TwiddleOpCons[F, B] = new TwiddleOpCons( - fb - ) - implicit def toTwiddleOpTwo[B](fb: F[B]): TwiddleOpTwo[F, B] = new TwiddleOpTwo(fb) - extension [A](fa: F[A]) - // TODO: Define *: here instead of with toTwiddleOpCons/Two methods above; doing so breaks a bunch of tests though + @annotation.targetName("cons") + def *:[B <: Tuple](fb: F[B])(using InvariantSemigroupal[F]): F[A *: B] = + fa.product(fb).imap[A *: B] { case (hd, tl) => hd *: tl } { case hd *: tl => (hd, tl) } + + @annotation.targetName("pair") + @annotation.nowarn + def *:[B](fb: F[B])(using InvariantSemigroupal[F]): F[A *: B *: EmptyTuple] = + fa.product(fb).imap[A *: B *: EmptyTuple] { case (a, b) => a *: b *: EmptyTuple } { + case a *: b *: EmptyTuple => (a, b) + } + def to[B](using iso: Iso[A, B], F: Invariant[F]): F[B] = fa.imap(iso.to)(iso.from) extension [A <: Tuple](fa: F[A]) @@ -51,13 +56,13 @@ trait TwiddleSyntax[F[_]]: object syntax: extension [F[_], A](fa: F[A]) @annotation.targetName("cons") - def *:[G[x] >: F[x], B <: Tuple](gb: G[B])(using InvariantSemigroupal[G]): G[A *: B] = - fa.product(gb).imap[A *: B] { case (hd, tl) => hd *: tl } { case hd *: tl => (hd, tl) } + def *:[B <: Tuple](fb: F[B])(using InvariantSemigroupal[F]): F[A *: B] = + fa.product(fb).imap[A *: B] { case (hd, tl) => hd *: tl } { case hd *: tl => (hd, tl) } @annotation.targetName("pair") @annotation.nowarn - def *:[G[x] >: F[x], B](gb: G[B])(using InvariantSemigroupal[G]): G[A *: B *: EmptyTuple] = - fa.product(gb).imap[A *: B *: EmptyTuple] { case (a, b) => a *: b *: EmptyTuple } { + def *:[B](fb: F[B])(using InvariantSemigroupal[F]): F[A *: B *: EmptyTuple] = + fa.product(fb).imap[A *: B *: EmptyTuple] { case (a, b) => a *: b *: EmptyTuple } { case a *: b *: EmptyTuple => (a, b) } @@ -67,24 +72,3 @@ object syntax: inline def dropUnits(using Invariant[F]): F[DropUnits[A]] = fa.imap(DropUnits.drop(_))(DropUnits.insert(_)) -final class TwiddleOpCons[F[_], B <: Tuple](private val self: F[B]) extends AnyVal: - // Workaround for https://github.com/typelevel/twiddles/pull/2 - @annotation.targetName("consFixedF") - def *:[A](fa: F[A])(using F: InvariantSemigroupal[F]): F[A *: B] = - *:[F, A](fa)(using F) - - def *:[G[x] >: F[x], A](ga: G[A])(using InvariantSemigroupal[G]): G[A *: B] = - ga.product(self).imap[A *: B] { case (hd, tl) => hd *: tl } { case hd *: tl => (hd, tl) } - -final class TwiddleOpTwo[F[_], B](private val self: F[B]) extends AnyVal: - // Workaround for https://github.com/typelevel/twiddles/pull/2 - @annotation.targetName("twoFixedF") - def *:[A]( - fa: F[A] - )(using F: InvariantSemigroupal[F]): F[A *: B *: EmptyTuple] = - *:[F, A](fa)(using F) - - def *:[G[x] >: F[x], A](ga: G[A])(using InvariantSemigroupal[G]): G[A *: B *: EmptyTuple] = - ga.product(self).imap[A *: B *: EmptyTuple] { case (a, b) => a *: b *: EmptyTuple } { - case a *: b *: EmptyTuple => (a, b) - }