From 6ec0dc6baee1bdc833aefef5ee5c037a401350c3 Mon Sep 17 00:00:00 2001 From: QueenJcloud Date: Mon, 20 Oct 2025 13:00:42 +0100 Subject: [PATCH 1/9] Add doctest example for Op in cats core --- core/src/main/scala/cats/data/Op.scala | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/core/src/main/scala/cats/data/Op.scala b/core/src/main/scala/cats/data/Op.scala index 372eb58865..6cc0b991a6 100644 --- a/core/src/main/scala/cats/data/Op.scala +++ b/core/src/main/scala/cats/data/Op.scala @@ -28,6 +28,28 @@ import cats.arrow.* * The dual category of some other category, `Arr`. */ final case class Op[Arr[_, _], A, B](run: Arr[B, A]) { + + /** + * Compose two `Op` values. Note that composition order is reversed compared to `Arr`. + * + * Example: + * {{{ + * import cats._ + * import cats.data._ + * + * val f: Int => String = _.toString + * val g: String => Int = _.length + * + * val opF = Op(f) + * val opG = Op(g) + * + * val composed = opF.compose(opG) + * // composed: cats.data.Op[Function1, Int, Int] + * + * composed.run(1234) + * // res0: Int = 4 + * }}} + */ def compose[Z](op: Op[Arr, Z, A])(implicit Arr: Compose[Arr]): Op[Arr, Z, B] = Op(Arr.compose(op.run, run)) @@ -35,6 +57,7 @@ final case class Op[Arr[_, _], A, B](run: Arr[B, A]) { Arr.eqv(run, op.run) } + object Op extends OpInstances sealed abstract private[data] class OpInstances extends OpInstances0 { From 2f325abb663ff4042ea38c7e56a336c9c450165b Mon Sep 17 00:00:00 2001 From: QueenJcloud Date: Tue, 21 Oct 2025 11:39:38 +0100 Subject: [PATCH 2/9] Add doctest for Op --- core/src/main/scala/cats/data/Op.scala | 39 ++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/core/src/main/scala/cats/data/Op.scala b/core/src/main/scala/cats/data/Op.scala index 6cc0b991a6..4caa02f2e2 100644 --- a/core/src/main/scala/cats/data/Op.scala +++ b/core/src/main/scala/cats/data/Op.scala @@ -19,13 +19,43 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package cats -package data +package cats.data -import cats.arrow.* +import cats.kernel.Eq +import cats.arrow.Compose /** - * The dual category of some other category, `Arr`. + * The `Op` class represents the dual of a morphism in category theory. + * + * In a normal category, arrows (or morphisms) have a direction `A => B`. + * The dual category reverses these arrows, making them `B => A`. + * The `Op` type is a simple wrapper that provides this “reversed” view. + * + * Practically, `Op` can be useful when you want to reason about or define + * operations in terms of their duals without modifying the original category. + * For example, when you have an existing `Compose` instance for a category, + * `Op` allows you to flip the composition order and explore properties of + * the dual structure. + * + * While `Compose` already defines both `compose` and `andThen` (and the `<<<` / `>>>` operators), + * `Op` exists as a separate abstraction to explicitly capture and work with + * the *dual category* concept in functional programming. + * + * Example: + * {{{ + * import cats._ + * import cats.data._ + * + * val f: Int => String = _.toString + * val g: String => Double = _.length.toDouble + * + * val opF = Op(f) + * val opG = Op(g) + * + * // Composition in Op reverses direction + * val composed = opF.compose(opG) // equivalent to g andThen f + * composed.run(1234) // 4.0 + * }}} */ final case class Op[Arr[_, _], A, B](run: Arr[B, A]) { @@ -57,7 +87,6 @@ final case class Op[Arr[_, _], A, B](run: Arr[B, A]) { Arr.eqv(run, op.run) } - object Op extends OpInstances sealed abstract private[data] class OpInstances extends OpInstances0 { From 7a4dddcafc35a01431d9a857ffa5de594607d693 Mon Sep 17 00:00:00 2001 From: QueenJcloud Date: Tue, 21 Oct 2025 12:47:46 +0100 Subject: [PATCH 3/9] fix formatting and add docs for Op usage --- core/src/main/scala/cats/data/Op.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/scala/cats/data/Op.scala b/core/src/main/scala/cats/data/Op.scala index 4caa02f2e2..cc68b8f23b 100644 --- a/core/src/main/scala/cats/data/Op.scala +++ b/core/src/main/scala/cats/data/Op.scala @@ -22,7 +22,7 @@ package cats.data import cats.kernel.Eq -import cats.arrow.Compose +import cats.arrow.{Category, Compose} /** * The `Op` class represents the dual of a morphism in category theory. From 0dc85296dae09faaad0efb98c32f5bc41044f64e Mon Sep 17 00:00:00 2001 From: QueenJcloud Date: Wed, 22 Oct 2025 10:11:01 +0100 Subject: [PATCH 4/9] refine Op.scala documentation and examples based on review feedback restored correct package structure (package cats; package data), simplified class-level Scaladoc for better clarity, replaced previous example with a more illustrative dual composition example --- core/src/main/scala/cats/data/Op.scala | 45 ++++++++++++-------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/core/src/main/scala/cats/data/Op.scala b/core/src/main/scala/cats/data/Op.scala index cc68b8f23b..11b7396178 100644 --- a/core/src/main/scala/cats/data/Op.scala +++ b/core/src/main/scala/cats/data/Op.scala @@ -17,44 +17,41 @@ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ + */ -package cats.data +package cats +package data +import cats.arrow.* import cats.kernel.Eq -import cats.arrow.{Category, Compose} +import cats.arrow.Compose /** - * The `Op` class represents the dual of a morphism in category theory. + * The dual category of some other category, `Arr`. * - * In a normal category, arrows (or morphisms) have a direction `A => B`. - * The dual category reverses these arrows, making them `B => A`. - * The `Op` type is a simple wrapper that provides this “reversed” view. + * In a normal category, `Arr` has a direction `A => B`. + * The dual category reverses the direction, making it `B => A`. * - * Practically, `Op` can be useful when you want to reason about or define + * The dual category can be useful when you want to reason about or define * operations in terms of their duals without modifying the original category. - * For example, when you have an existing `Compose` instance for a category, - * `Op` allows you to flip the composition order and explore properties of - * the dual structure. - * - * While `Compose` already defines both `compose` and `andThen` (and the `<<<` / `>>>` operators), - * `Op` exists as a separate abstraction to explicitly capture and work with - * the *dual category* concept in functional programming. + * In other words, the dual category provides a "reversed" view to the original category. * * Example: * {{{ - * import cats._ - * import cats.data._ + * import cats.arrow.Compose + * import cats.data.Op + * import cats.syntax.all.* * - * val f: Int => String = _.toString - * val g: String => Double = _.length.toDouble + * val f: String => String = a => s"f($a)" + * val g: String => String = b => s"g($b)" * - * val opF = Op(f) - * val opG = Op(g) + * // `>>>` is an alias for `andThen` + * (f >>> g)("a") + * // res0: String = g(f(a)) * - * // Composition in Op reverses direction - * val composed = opF.compose(opG) // equivalent to g andThen f - * composed.run(1234) // 4.0 + * // `Op` reverses the composition + * (Op(f) >>> Op(g)).run("a") + * // res1: String = f(g(a)) * }}} */ final case class Op[Arr[_, _], A, B](run: Arr[B, A]) { From a8a4ba6fe13fc5d69b59edecdef633026d71b3bf Mon Sep 17 00:00:00 2001 From: QueenJcloud Date: Wed, 22 Oct 2025 19:25:28 +0100 Subject: [PATCH 5/9] headercheck fixed --- core/src/main/scala/cats/data/Op.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/scala/cats/data/Op.scala b/core/src/main/scala/cats/data/Op.scala index 11b7396178..8eeac5adcf 100644 --- a/core/src/main/scala/cats/data/Op.scala +++ b/core/src/main/scala/cats/data/Op.scala @@ -17,7 +17,7 @@ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ +*/ package cats package data From 36cd17f64972f6848b48b151530fb4ee5c6914f6 Mon Sep 17 00:00:00 2001 From: QueenJcloud Date: Thu, 23 Oct 2025 09:13:03 +0100 Subject: [PATCH 6/9] Format code with scalafmt and fix header issues in Op.scala --- core/src/main/scala/cats/data/Op.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/scala/cats/data/Op.scala b/core/src/main/scala/cats/data/Op.scala index 8eeac5adcf..f0dfaa5bc5 100644 --- a/core/src/main/scala/cats/data/Op.scala +++ b/core/src/main/scala/cats/data/Op.scala @@ -17,7 +17,7 @@ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ + */ package cats package data From ff1e1f0a92717b72732ab2ffbc6b121f976d56d0 Mon Sep 17 00:00:00 2001 From: QueenJcloud Date: Thu, 23 Oct 2025 09:19:42 +0100 Subject: [PATCH 7/9] Format code with scalafmt and fix header issues in Op.scala --- core/src/main/scala/cats/data/Op.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/scala/cats/data/Op.scala b/core/src/main/scala/cats/data/Op.scala index f0dfaa5bc5..8eeac5adcf 100644 --- a/core/src/main/scala/cats/data/Op.scala +++ b/core/src/main/scala/cats/data/Op.scala @@ -17,7 +17,7 @@ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ +*/ package cats package data From 95ed9deeec98325b78b90f9fcc086b878138f33b Mon Sep 17 00:00:00 2001 From: QueenJcloud Date: Thu, 23 Oct 2025 10:21:22 +0100 Subject: [PATCH 8/9] Format code with scalafmt and fix header issues in Op.scala --- core/src/main/scala/cats/data/Op.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/scala/cats/data/Op.scala b/core/src/main/scala/cats/data/Op.scala index 8eeac5adcf..f0dfaa5bc5 100644 --- a/core/src/main/scala/cats/data/Op.scala +++ b/core/src/main/scala/cats/data/Op.scala @@ -17,7 +17,7 @@ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ + */ package cats package data From b353e25f2fa4b8f0eadc02a91406045d82f80224 Mon Sep 17 00:00:00 2001 From: QueenJcloud Date: Fri, 24 Oct 2025 09:48:43 +0100 Subject: [PATCH 9/9] Remove unnecessary imports in Op.scala as per review feedback --- core/src/main/scala/cats/data/Op.scala | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/src/main/scala/cats/data/Op.scala b/core/src/main/scala/cats/data/Op.scala index f0dfaa5bc5..86bea83cec 100644 --- a/core/src/main/scala/cats/data/Op.scala +++ b/core/src/main/scala/cats/data/Op.scala @@ -23,8 +23,6 @@ package cats package data import cats.arrow.* -import cats.kernel.Eq -import cats.arrow.Compose /** * The dual category of some other category, `Arr`.