diff --git a/README.md b/README.md
index b111884..a645a21 100644
--- a/README.md
+++ b/README.md
@@ -74,17 +74,19 @@ be printed, with titles and labels in the following formats:
import polynomial.`object`.Monomial.{Store, Interface}
import polynomial.mermaid.{Format, Mermaid, given}
import polynomial.morphism.~>
+import polynomial.product.⊗
-type F[Y] = (Store[Boolean, _] ~> Interface[Int, Int, _])[Y]
+type F[Y] = ((Store[Boolean, _] ⊗ Store[Boolean, _]) ~> (Interface[Int, Int, _] ⊗ Interface[Int, Int, _]))[Y]
val M: Mermaid[F] = summon[Mermaid[F]]
-// M: Mermaid[F] = polynomial.mermaid.Mermaid$$anon$1@56887c6
+// M: Mermaid[F] = polynomial.mermaid.Mermaid$$anon$5@1264038d
println(M.showTitledGraph(titleFmt = Format.Generic, graphFmt = Format.Generic))
// ```mermaid
// graph LR;
-// TitleStart[ ]:::hidden~~~TitleBody[S𝑦S → B𝑦A]:::title~~~TitleEnd[ ]:::hidden
-// A:::hidden---|A|S[S]---|B|B:::hidden;
+// TitleStart[ ]:::hidden~~~TitleBody[S1𝑦S1 ⊗ S2𝑦S2 → B1𝑦A1 ⊗ B2𝑦A2]:::title~~~TitleEnd[ ]:::hidden
+// A1:::hidden---|A1|S1[S1]---|B1|B1:::hidden;
+// A2:::hidden---|A2|S2[S2]---|B2|B2:::hidden;
//
// classDef empty fill:background;
// classDef point width:0px, height:0px;
diff --git a/docs/readme.md b/docs/readme.md
index 155e492..579758e 100644
--- a/docs/readme.md
+++ b/docs/readme.md
@@ -74,8 +74,9 @@ be printed, with titles and labels in the following formats:
import polynomial.`object`.Monomial.{Store, Interface}
import polynomial.mermaid.{Format, Mermaid, given}
import polynomial.morphism.~>
+import polynomial.product.⊗
-type F[Y] = (Store[Boolean, _] ~> Interface[Int, Int, _])[Y]
+type F[Y] = ((Store[Boolean, _] ⊗ Store[Boolean, _]) ~> (Interface[Int, Int, _] ⊗ Interface[Int, Int, _]))[Y]
val M: Mermaid[F] = summon[Mermaid[F]]
diff --git a/modules/mermaid/shared/src/main/scala/polynomial/mermaid/Mermaid.scala b/modules/mermaid/shared/src/main/scala/polynomial/mermaid/Mermaid.scala
index de52035..381a528 100644
--- a/modules/mermaid/shared/src/main/scala/polynomial/mermaid/Mermaid.scala
+++ b/modules/mermaid/shared/src/main/scala/polynomial/mermaid/Mermaid.scala
@@ -401,12 +401,12 @@ object Mermaid:
Q2: MermaidQ[Monomial.Interface[A2, B2, _]],
): Mermaid[PolyMap[Monomial.Store[S1, _] ⊗ Monomial.Store[S2, _], Monomial.Interface[A1, B1, _] ⊗ Monomial.Interface[A2, B2, _], _]] =
new Mermaid[PolyMap[Monomial.Store[S1, _] ⊗ Monomial.Store[S2, _], Monomial.Interface[A1, B1, _] ⊗ Monomial.Interface[A2, B2, _], _]]:
- private val labelS1 = "S1"
- private val labelS2 = "S2"
- private val labelA1 = "A1"
- private val labelA2 = "A2"
- private val labelB1 = "B1"
- private val labelB2 = "B2"
+ private val labelS1 = "S1"
+ private val labelS2 = "S2"
+ private val labelA1 = "A1"
+ private val labelA2 = "A2"
+ private val labelB1 = "B1"
+ private val labelB2 = "B2"
private val nodeS1 = "S1"
private val nodeS2 = "S2"
private val nodeA1 = "A1"
diff --git a/modules/poly/shared/src/main/scala/polynomial/morphism/PolyMap.scala b/modules/poly/shared/src/main/scala/polynomial/morphism/PolyMap.scala
index c262540..0f3b755 100644
--- a/modules/poly/shared/src/main/scala/polynomial/morphism/PolyMap.scala
+++ b/modules/poly/shared/src/main/scala/polynomial/morphism/PolyMap.scala
@@ -24,7 +24,7 @@ object PolyMap:
type Phi[P[_], Q[_], Y] = (P[Y], Q[Y]) match
case (Binomial.Interface[a1, b1, a2, b2, Y], Binomial.Interface[a3, b3, a4, b4, Y]) => (b1 => b3, b2 => b4)
- case (Binomial.Interface[a1, b1, a2, b2, Y], Monomial.Interface[a3, b3, Y]) => (b1 => b3, b2 => b3)
+ case (Binomial.Interface[a1, b1, a2, b2, Y], Monomial.Interface[a3, b3, Y]) => (b1 => b3, b2 => b3)
case (Monomial.Interface[a1, b1, Y], Binomial.Interface[a3, b3, a4, b4, Y]) => (b1 => b3, b1 => b4)
case (Monomial.Interface[a1, b1, Y], Monomial.Interface[a2, b2, Y]) => b1 => b2
case (PolyMap[p, q, Y], Binomial.Interface[a3, b3, a4, b4, Y]) => Phi[p, Binomial.Interface[a3, b3, a4, b4, _], Y]
@@ -33,10 +33,11 @@ object PolyMap:
case (Monomial.Store[s, Y], Binomial.Interface[a1, b1, a2, b2, Y]) => (s => b1, s => b2)
case (Monomial.Store[s, Y], Monomial.Interface[a, b, Y]) => s => b
case (Monomial.Store[s, Y], Composition[p, q, Y]) => (Phi[Monomial.Store[s, _], p, Y], Phi[p, q, Y])
+ case (Tensor[p, q, Y], Monomial.Store[s1, Y]) => Phi[Tensor.DayConvolution[p, q, _], Monomial.Store[s1, _], Y]
case (Tensor[p, q, Y], Monomial.Interface[a1, b1, Y]) => Phi[Tensor.DayConvolution[p, q, _], Monomial.Interface[a1, b1, _], Y]
case (Tensor[p, q, Y], Binomial.Interface[a1, b1, a2, b2, Y]) => Phi[Tensor.DayConvolution[p, q, _], Binomial.Interface[a1, b1, a2, b2, _], Y]
case (Tensor[o, p, Y], Tensor[q, r, Y]) => Phi[Tensor.DayConvolution[o, p, _], Tensor.DayConvolution[q, r, _], Y]
-
+
type PhiSharp[P[_], Q[_], Y] = (P[Y], Q[Y]) match
case (Binomial.Interface[a1, b1, a2, b2, Y], Binomial.Interface[a3, b3, a4, b4, Y]) => ((b1, a3) => a1, (b2, a4) => a2)
case (Binomial.Interface[a1, b1, a2, b2, Y], Monomial.Interface[a3, b3, Y]) => ((b1, a3) => a1, (b2, a3) => a2)
@@ -50,4 +51,5 @@ object PolyMap:
case (PolyMap[o, p, Y], Tensor[q, r, Y]) => PhiSharp[o, Tensor[q, r, _], Y]
case (Tensor[p, q, Y], Binomial.Interface[a1, b1, a2, b2, Y]) => PhiSharp[Tensor.DayConvolution[p, q, _], Binomial.Interface[a1, b1, a2, b2, _], Y]
case (Tensor[p, q, Y], Monomial.Interface[a1, b1, Y]) => PhiSharp[Tensor.DayConvolution[p, q, _], Monomial.Interface[a1, b1, _], Y]
+ case (Tensor[p, q, Y], Monomial.Store[s1, Y]) => PhiSharp[Tensor.DayConvolution[p, q, _], Monomial.Store[s1, _], Y]
case (Tensor[o, p, Y], Tensor[q, r, Y]) => PhiSharp[Tensor.DayConvolution[o, p, _], Tensor.DayConvolution[q, r, _], Y]
\ No newline at end of file
diff --git a/modules/poly/shared/src/main/scala/polynomial/morphism/methods/andThen.scala b/modules/poly/shared/src/main/scala/polynomial/morphism/methods/andThen.scala
index 2f8ea88..afcdbeb 100644
--- a/modules/poly/shared/src/main/scala/polynomial/morphism/methods/andThen.scala
+++ b/modules/poly/shared/src/main/scala/polynomial/morphism/methods/andThen.scala
@@ -70,7 +70,7 @@ object andThen:
def φ: PolyMap.Phi[(Monomial.Store[S1, _] ⊗ Monomial.Store[S2, _]) ~> (Monomial.Interface[(A, B), C, _] ⊗ Monomial.Interface[C, B, _]), Monomial.Interface[A, A => C, _], Y] =
p.φ.andThen(w.φ)
def `φ#`: PolyMap.PhiSharp[(Monomial.Store[S1, _] ⊗ Monomial.Store[S2, _]) ~> (Monomial.Interface[(A, B), C, _] ⊗ Monomial.Interface[C, B, _]), Monomial.Interface[A, A => C, _], Y] =
- (s, a) => p.`φ#`(s, w.`φ#`(p.φ(s), a))
+ (s, a) => p.`φ#`(s, w.`φ#`(p.φ(s), a))
extension [S1, S2, A1, B1, A2, B2, Y] (p: PolyMap[Monomial.Store[S1, _] ⊗ Monomial.Store[S2, _], Monomial.Interface[A1, B1, _] ⊗ Monomial.Interface[A2, B2, _], Y])
@scala.annotation.targetName("andThenTensoredStoreTensoredMonoToTensoredMono")
@@ -87,19 +87,40 @@ object andThen:
@scala.annotation.targetName("andThenTensorStoreTensorBiToBi")
def andThen(
w: PolyMap[Binomial.Interface[A1, B1, A2, B2, _] ⊗ Binomial.Interface[A3, B3, A4, B4, _], Binomial.Interface[A1, A1 => B3, A2, A2 => B4, _], Y],
- f: S2 => A3,
- g: S1 => A4,
- h: B1 => A3,
- i: B2 => A4
+ // f: S2 => A3,
+ // g: S1 => A4,
+ // h: B1 => A3,
+ // i: B2 => A4
): PolyMap[PolyMap[(Monomial.Store[S1, _] ⊗ Monomial.Store[S2, _]), (Binomial.Interface[A1, B1, A2, B2, _] ⊗ Binomial.Interface[A3, B3, A4, B4, _]), _], Binomial.Interface[A1, A1 => B3, A2, A2 => B4, _], Y] =
new PolyMap[PolyMap[(Monomial.Store[S1, _] ⊗ Monomial.Store[S2, _]), (Binomial.Interface[A1, B1, A2, B2, _] ⊗ Binomial.Interface[A3, B3, A4, B4, _]), _], Binomial.Interface[A1, A1 => B3, A2, A2 => B4, _], Y]:
def φ: PolyMap.Phi[PolyMap[(Monomial.Store[S1, _] ⊗ Monomial.Store[S2, _]), (Binomial.Interface[A1, B1, A2, B2, _] ⊗ Binomial.Interface[A3, B3, A4, B4, _]), _], Binomial.Interface[A1, A1 => B3, A2, A2 => B4, _], Y] =
(
- s => a1 => p.φ._1(p.`φ#`._1(s, (a1, h(p.φ._1(s)._1))))._2,
- s => a2 => p.φ._2(p.`φ#`._2(s, (a2, i(p.φ._2(s)._1))))._2
+ p.φ._1.andThen(w.φ._1),
+ p.φ._2.andThen(w.φ._2),
+ // s => a1 => p.φ._1(p.`φ#`._1(s, (a1, h(p.φ._1(s)._1))))._2,
+ // s => a2 => p.φ._2(p.`φ#`._2(s, (a2, i(p.φ._2(s)._1))))._2
)
def `φ#`: PolyMap.PhiSharp[PolyMap[(Monomial.Store[S1, _] ⊗ Monomial.Store[S2, _]), (Binomial.Interface[A1, B1, A2, B2, _] ⊗ Binomial.Interface[A3, B3, A4, B4, _]), _], Binomial.Interface[A1, A1 => B3, A2, A2 => B4, _], Y] =
(
- (s: (S1, S2), a1: A1) => p.`φ#`._1(s, (a1, f(s._2))),
- (s: (S1, S2), a2: A2) => p.`φ#`._2(s, (a2, g(s._1)))
- )
\ No newline at end of file
+ (s, a) => p.`φ#`._1(s, w.`φ#`._1(p.φ._1(s), a)),
+ (s, a) => p.`φ#`._2(s, w.`φ#`._2(p.φ._2(s), a)),
+ // (s: (S1, S2), a1: A1) => p.`φ#`._1(s, (a1, f(s._2))),
+ // (s: (S1, S2), a2: A2) => p.`φ#`._2(s, (a2, g(s._1)))
+ )
+
+ extension [S1, S2, S3, A1, B1, A2, B2, A3, B3, A4, B4, Y] (
+ p: PolyMap[(Monomial.Store[S1, _] ⊗ Monomial.Store[S2, _] ⊗ Monomial.Store[S3, _]), (Monomial.Interface[A1, B1, _] ⊗ Monomial.Interface[A2, B2, _] ⊗ Monomial.Interface[A3, B3, _]), Y]
+ )
+ @scala.annotation.targetName("andThenMsMsMstoMiMiMi")
+ def andThen(
+ w: PolyMap[(Monomial.Interface[A1, B1, _] ⊗ Monomial.Interface[A2, B2, _] ⊗ Monomial.Interface[A3, B3, _]), Monomial.Interface[Unit, Unit => Unit, _], Y],
+ f: S1 => A1,
+ g: S2 => A2,
+ h: S3 => A3,
+ ): PolyMap[PolyMap[(Monomial.Store[S1, _] ⊗ Monomial.Store[S2, _] ⊗ Monomial.Store[S3, _]), (Monomial.Interface[A1, B1, _] ⊗ Monomial.Interface[A2, B2, _] ⊗ Monomial.Interface[A3, B3, _]), _], Monomial.Interface[Unit, Unit => Unit, _], Y] =
+ new PolyMap[PolyMap[(Monomial.Store[S1, _] ⊗ Monomial.Store[S2, _] ⊗ Monomial.Store[S3, _]), (Monomial.Interface[A1, B1, _] ⊗ Monomial.Interface[A2, B2, _] ⊗ Monomial.Interface[A3, B3, _]), _], Monomial.Interface[Unit, Unit => Unit, _], Y]:
+ def φ: PolyMap.Phi[PolyMap[(Monomial.Store[S1, _] ⊗ Monomial.Store[S2, _] ⊗ Monomial.Store[S3, _]), (Monomial.Interface[A1, B1, _] ⊗ Monomial.Interface[A2, B2, _] ⊗ Monomial.Interface[A3, B3, _]), _], Monomial.Interface[Unit, Unit => Unit, _], Y] =
+ p.φ.andThen(w.φ)
+ def `φ#`: PolyMap.PhiSharp[PolyMap[(Monomial.Store[S1, _] ⊗ Monomial.Store[S2, _] ⊗ Monomial.Store[S3, _]), (Monomial.Interface[A1, B1, _] ⊗ Monomial.Interface[A2, B2, _] ⊗ Monomial.Interface[A3, B3, _]), _], Monomial.Interface[Unit, Unit => Unit, _], Y] =
+ (s, a) => p.`φ#`(s, w.`φ#`(p.φ(s), a))
+ // (s, _) => p.`φ#`(s, ((f(s._1._1), g(s._1._2)), h(s._2)))
diff --git a/modules/poly/shared/src/main/scala/polynomial/product/Tensor.scala b/modules/poly/shared/src/main/scala/polynomial/product/Tensor.scala
index 9ee4c56..3dd4f90 100644
--- a/modules/poly/shared/src/main/scala/polynomial/product/Tensor.scala
+++ b/modules/poly/shared/src/main/scala/polynomial/product/Tensor.scala
@@ -1,7 +1,7 @@
package polynomial.product
-import polynomial.`object`.{Binomial, Monomial}
import polynomial.morphism.PolyMap
+import polynomial.`object`.{Binomial, Monomial}
type ⊗[P[_], Q[_]] = Tensor[P, Q, _]
@@ -10,6 +10,10 @@ object Tensor:
type DayConvolution[P[_], Q[_], Y] = (P[Y], Q[Y]) match
case (Binomial.Interface[a1, b1, a2, b2, Y], Binomial.Interface[a3, b3, a4, b4, Y]) => Binomial.Interface[(a1, a3), (b1, b3), (a2, a4), (b2, b4), Y]
+ case (Monomial.Interface[a1, b1, Y], Binomial.Interface[a2, b2, a3, b3, Y]) => Binomial.Interface[(a1, a2), (b1, b2), (a1, a3), (b1, b3), Y]
case (Monomial.Interface[a1, b1, Y], Monomial.Interface[a2, b2, Y]) => Monomial.Interface[(a1, a2), (b1, b2), Y]
case (Monomial.Store[s1, Y], Monomial.Store[s2, Y]) => Monomial.Store[(s1, s2), Y]
- case (PolyMap[o, p, Y], PolyMap[q, r, Y]) => PolyMap[DayConvolution[o, q, _], DayConvolution[p, r, _], Y]
\ No newline at end of file
+ case (PolyMap[o, p, Y], PolyMap[q, r, Y]) => PolyMap[DayConvolution[o, q, _], DayConvolution[p, r, _], Y]
+ case (Tensor[o, p, Y], Binomial.Interface[a1, b1, a2, b2, Y]) => DayConvolution[DayConvolution[o, p, _], Binomial.Interface[a1, b1, a2, b2, _], Y]
+ case (Tensor[o, p, Y], Monomial.Interface[a1, b1, Y]) => DayConvolution[DayConvolution[o, p, _], Monomial.Interface[a1, b1, _], Y]
+ case (Tensor[o, p, Y], Monomial.Store[s1, Y]) => DayConvolution[DayConvolution[o, p, _], Monomial.Store[s1, _], Y]
\ No newline at end of file