From 38f93c337b23a4902d9eb058b9fd67710e248bb3 Mon Sep 17 00:00:00 2001 From: Julian Peeters Date: Wed, 20 Dec 2023 20:53:18 -0800 Subject: [PATCH] Add polynomial-mermaid module Basics for generating mermaid definitions for PolyMaps --- README.md | 38 +++++++++++--- build.sbt | 7 ++- docs/readme.md | 37 +++++++++++--- .../scala/polynomial/mermaid/Mermaid.scala | 49 +++++++++++++++++++ 4 files changed, 114 insertions(+), 17 deletions(-) create mode 100644 modules/mermaid/shared/src/main/scala/polynomial/mermaid/Mermaid.scala diff --git a/README.md b/README.md index c5d1c95..14c60a2 100644 --- a/README.md +++ b/README.md @@ -16,19 +16,41 @@ Based on the polynomial functors described in [Niu and Spivak](https://topos.sit #### `polynomial` The `polynomial` library provides the following implementation of poly: - - objects: built-in ADTs representing `Monomial`, `Binomial`, `Trinomial` functors + - objects: built-in ADTs representing `Monomial`, `Binomial`, `Trinomial`, and `Store` functors - morphisms: `PolyMap`, a natural transformation between polynomial functors - - products: `Tensor`, a type match on functors, yielding their Day convolution + - products: `Tensor`, a type match on functors, yielding a parallel product ```scala -import polynomial.`object`.Monomial +import polynomial.`object`.{Binomial, Monomial, Store} import polynomial.morphism.~> import polynomial.product.⊗ -type Plant[Y] = Monomial[(Byte, Byte => Char), Char, Y] -type Controller[Y] = Monomial[Char, Byte => Char, Y] -type System[Y] = Monomial[Byte, Byte => Char, Y] +type `2y²` = Store[Boolean, _] +type `2y⁵¹²` = Monomial[(Byte, Boolean), Boolean, _] +type `y² + 2y` = Binomial[Boolean, Unit, Unit, Boolean, _] +type `y² + 2y → 2y⁵¹²` = (`y² + 2y` ~> `2y⁵¹²`)[_] +type `4y⁴` = (`2y²` ⊗ `2y²`)[_] +``` + +#### `polynomial-mermaid` + +Certain lenses lend themselves to graphical interpretation: + +```scala +import polynomial.`object`.{Store, Monomial} +import polynomial.mermaid.Mermaid +import polynomial.morphism.~> + +type P[Y] = (Store[Int, _] ~> Monomial[Char, Unit, _])[Y] + +println(s"${summon[Mermaid[P]].showSpecific}") +// ```mermaid +// graph LR; +// A[Char]:::hidden-->|Char|S[Int]-->|Unit|B[Unit]:::hidden; +// ``` +``` -type ω[Y] = ((Plant ⊗ Controller) ~> System)[Y] +```mermaid +graph LR; + A[Char]:::hidden-->|Char|S[java.lang.String]-->|Unit|B[Unit]:::hidden; ``` -(Note: example adapted from the poly book, by [Niu and Spivak](https://topos.site/poly-book.pdf)) diff --git a/build.sbt b/build.sbt index 36246f5..9e37a3a 100644 --- a/build.sbt +++ b/build.sbt @@ -35,6 +35,11 @@ lazy val poly = crossProject(JSPlatform, JVMPlatform, NativePlatform) ) ) +lazy val mermaid = crossProject(JSPlatform, JVMPlatform, NativePlatform) + .in(file("modules/mermaid")) + .settings(name := "polynomial-mermaid") + .dependsOn(poly) + lazy val docs = project.in(file("docs/gitignored")) .settings( mdocOut := file("."), @@ -44,6 +49,6 @@ lazy val docs = project.in(file("docs/gitignored")) "VERSION" -> version.value.takeWhile(_ != '+'), ) ) - .dependsOn(poly.jvm) + .dependsOn(poly.jvm, mermaid.jvm) .enablePlugins(MdocPlugin) .enablePlugins(NoPublishPlugin) \ No newline at end of file diff --git a/docs/readme.md b/docs/readme.md index f235ce8..85f4a51 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -16,19 +16,40 @@ Based on the polynomial functors described in [Niu and Spivak](https://topos.sit #### `polynomial` The `polynomial` library provides the following implementation of poly: - - objects: built-in ADTs representing `Monomial`, `Binomial`, `Trinomial` functors + - objects: built-in ADTs representing `Monomial`, `Binomial`, `Trinomial`, and `Store` functors - morphisms: `PolyMap`, a natural transformation between polynomial functors - - products: `Tensor`, a type match on functors, yielding their Day convolution + - products: `Tensor`, a type match on functors, yielding a parallel product ```scala mdoc -import polynomial.`object`.Monomial +import polynomial.`object`.{Binomial, Monomial, Store} import polynomial.morphism.~> import polynomial.product.⊗ -type Plant[Y] = Monomial[(Byte, Byte => Char), Char, Y] -type Controller[Y] = Monomial[Char, Byte => Char, Y] -type System[Y] = Monomial[Byte, Byte => Char, Y] +type `2y²` = Store[Boolean, _] +type `2y⁵¹²` = Monomial[(Byte, Boolean), Boolean, _] +type `y² + 2y` = Binomial[Boolean, Unit, Unit, Boolean, _] +type `y² + 2y → 2y⁵¹²` = (`y² + 2y` ~> `2y⁵¹²`)[_] +type `4y⁴` = (`2y²` ⊗ `2y²`)[_] +``` + +#### `polynomial-mermaid` + +```scala mdoc:reset +import polynomial.`object`.{Store, Monomial} +import polynomial.mermaid.Mermaid +import polynomial.morphism.~> + +type P[Y] = (Store[Int, _] ~> Monomial[Char, Unit, _])[Y] -type ω[Y] = ((Plant ⊗ Controller) ~> System)[Y] +println(s"${summon[Mermaid[P]].showSpecific}") ``` -(Note: example adapted from the poly book, by [Niu and Spivak](https://topos.site/poly-book.pdf)) + +```scala mdoc:reset:passthrough +import polynomial.`object`.{Store, Monomial} +import polynomial.mermaid.Mermaid +import polynomial.morphism.~> + +type P[Y] = (Store[String, _] ~> Monomial[Char, Unit, _])[Y] + +println(s"${summon[Mermaid[P]].showSpecific}") +``` \ No newline at end of file diff --git a/modules/mermaid/shared/src/main/scala/polynomial/mermaid/Mermaid.scala b/modules/mermaid/shared/src/main/scala/polynomial/mermaid/Mermaid.scala new file mode 100644 index 0000000..5217729 --- /dev/null +++ b/modules/mermaid/shared/src/main/scala/polynomial/mermaid/Mermaid.scala @@ -0,0 +1,49 @@ +package polynomial.mermaid + +import polynomial.morphism.PolyMap +import polynomial.`object`.{Monomial, Store} +import scala.reflect.ClassTag + +trait Mermaid[P[_]]: + def showGeneric: String + def showSpecific: String + +object Mermaid: + + given moore[S, A, B](using + S: ClassTag[S], + A: ClassTag[A], + B: ClassTag[B] + ): Mermaid[PolyMap[Store[S, _], Monomial[A, B, _], _]] = + new Mermaid[PolyMap[Store[S, _], Monomial[A, B, _], _]]: + + def showGeneric: String = + s"""|```mermaid + |graph LR; + | A:::hidden-->|A|S-->|B|B:::hidden; + |```""".stripMargin + + def showSpecific: String = + s"""|```mermaid + |graph LR; + | A[${A.toString}]:::hidden-->|${A.toString}|S[${S.toString}]-->|${B.toString}|B[${B.toString}]:::hidden; + |```""".stripMargin + + given mealy[S, A, B](using + S: ClassTag[S], + A: ClassTag[A], + B: ClassTag[B] + ): Mermaid[PolyMap[Store[S, _], Monomial[A, A => B, _], _]] = + new Mermaid[PolyMap[Store[S, _], Monomial[A, A => B, _], _]]: + + def showGeneric: String = + s"""|```mermaid + |graph LR; + | A:::hidden-->|A|S-->|B|B:::hidden; + |```""".stripMargin + + def showSpecific: String = + s"""|```mermaid + |graph LR; + | A[${A.toString}]:::hidden-->|${A.toString}|S[${S.toString}]-->|${A.toString} => ${B.toString}|B[${A.toString} => ${B.toString}]:::hidden; + |```""".stripMargin \ No newline at end of file