Last active
February 10, 2020 11:29
-
-
Save tarao/80d52dff89cbbc6bdf0e07bc26b0af54 to your computer and use it in GitHub Desktop.
Category-theoretic universal product representation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import product2.|*| | |
package object instance { | |
implicit val instanceProduct2: universal.Product2[|*|] = | |
new universal.Product2[|*|] { | |
override def p1[A, B](p: A |*| B): A = product2.π1(p) | |
override def p2[A, B](p: A |*| B): B = product2.π2(p) | |
override def mediate[A, B, C](implicit | |
wedge: universal.Wedge[C, A, B] | |
): C => A |*| B = product2.mediate(wedge.w1, wedge.w2) | |
} | |
implicit val instanceTuple2: universal.Product2[Tuple2] = | |
new universal.Product2[Tuple2] { | |
override def p1[A, B](p: (A, B)): A = p._1 | |
override def p2[A, B](p: (A, B)): B = p._2 | |
override def mediate[A, B, C](implicit | |
wedge: universal.Wedge[C, A, B] | |
): C => (A, B) = (c: C) => (wedge.w1(c), wedge.w2(c)) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package object product2 { | |
sealed trait |*|[A, B] { | |
def apply[C](f: (A, B) => C): C | |
} | |
object |*| { | |
def apply[A, B](a: A, b: B): |*|[A, B] = new |*|[A, B] { | |
override def apply[C](f: (A, B) => C): C = f(a, b) | |
override def toString = s"<$a, $b>" | |
} | |
} | |
def π1[A, B](x: A |*| B): A = x((a: A, b: B) => a) | |
def π2[A, B](x: A |*| B): B = x((a: A, b: B) => b) | |
// mediating | |
def mediate[A, B, C](f: C => A, g: C => B): C => A |*| B = | |
(c: C) => |*|(f(c), g(c)) | |
// example usage of mediating | |
def fromScala[A, B](t: (A, B)): A |*| B = | |
mediate[A, B, (A, B)](_._1, _._2)(t) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scala.language.higherKinds | |
package object universal { | |
trait Wedge[W, A, B] { | |
def w1(w: W): A | |
def w2(w: W): B | |
} | |
trait Product2[P[_, _]] { | |
def p1[A, B](p: P[A, B]): A | |
def p2[A, B](p: P[A, B]): B | |
def mediate[A, B, C](implicit | |
wedge: Wedge[C, A, B] | |
): C => P[A, B] | |
} | |
def π1[A, B, P[_, _]](p: P[A, B])(implicit product: Product2[P]): A = | |
product.p1(p) | |
def π2[A, B, P[_, _]](p: P[A, B])(implicit product: Product2[P]): B = | |
product.p2(p) | |
implicit def product2IsWedge[A, B, P[_, _]](implicit | |
product: Product2[P] | |
): Wedge[P[A, B], A, B] = | |
new Wedge[P[A, B], A, B] { | |
def w1(w: P[A, B]): A = product.p1(w) | |
def w2(w: P[A, B]): B = product.p2(w) | |
} | |
implicit class WedgeOps[W, A, B](val w: W)(implicit | |
wedge: Wedge[W, A, B] | |
) { | |
def toProduct[P[_, _]](implicit | |
product: Product2[P], | |
): P[A, B] = product.mediate[A, B, W](wedge)(w) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
User-defined tuple-like type
Use tuple-like type universally