Created
September 26, 2019 16:50
-
-
Save gustavofranke/5a5b1214f63f17faa645a252b521573c to your computer and use it in GitHub Desktop.
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
/** | |
* @see https://www.youtube.com/watch?v=UjSQlUjuZWQ | |
* @see https://bartoszmilewski.com/2019/07/03/programming-with-universal-constructions/ | |
*/ | |
object BartozUniversalsConstructions { | |
// C | |
// / | \ | |
// / | \ | |
// / | \ | |
// / | h \ | |
// f / v \ g | |
// | AxB | | |
// | pi2 / \ pi1 | | |
// | / \ | | |
// | / \ | | |
// | / \ | | |
// v v v v | |
// A B | |
type A | |
type B | |
type C | |
val product: (A, B) = ??? | |
val pi1 = (product: (A, B)) => product._1 | |
val pi2 = (product: (A, B)) => product._2 | |
val h: C => (A, B) = ??? | |
// val f = pi1 compose h = ??? | |
// val g = pi2 compose h = ??? | |
def fanout[C, A, B](fst: C => A, snd: C => B): C => (A, B) = c => (fst(c), snd(c)) | |
// Unit | |
// / | \ | |
// / | \ | |
// / | \ | |
// / | h \ | |
// f / v \ g | |
// | AxB | | |
// | pi2 / \ pi1 | | |
// | / \ | | |
// | / \ | | |
// | / \ | | |
// v v v v | |
// A B | |
val unit: Unit = () | |
val x: Unit => A = ??? | |
val y: Unit => B = ??? | |
def fanin[C, A, B](h: C => (A, B)): (C => A, C => B) = (h(_)._1, h(_)._2) | |
// (A, B) | |
// / | \ | |
// ._1/ | \ ._2 | |
// / | \ | |
// / |bimap \ | |
// A v v v B | |
// | (A', B') | | |
// | ._1 / \ ._2 | | |
// | / \ | | |
// | / \ | | |
// | / \ | | |
// v v v v | |
// A' B' | |
def bimap[A, A1, B, B1](f: A => A1, g: B => B1): ((A, B)) => (A1, B1) = | |
fanout(f compose (_._1), g compose (_._2)) | |
def either[C, A, B](f: A => C, g: B => C): Either[A, B] => C = _.fold(f, g) | |
// { | |
// case Left(a) => f(a) | |
// case Right(b) => g(b) | |
// } | |
// A B | |
// |\ right/ | | |
// | \left / | | |
// | \ / | | |
// | v v | | |
// f | A + B | g | |
// \ |either/ | |
// \ | / | |
// \ | / | |
// \ | / | |
// v v v | |
// C | |
def foo[C, A, B](h: Either[A, B] => C): (A => C, B => C) = (a => h(Left(a)), b => h(Right(b))) | |
// AxC BxC | |
// |\ right/ | | |
// | \left / | | |
// | \ / | | |
// | v v | | |
// f | AxC + BxC | g | |
// \ | / | |
// \ |h / | |
// \ | / | |
// \ | / | |
// v v v | |
// (A + B) x C | |
def left[A](a: A): Either[A, Nothing] = Left(a) | |
def right[B](b: B): Either[Nothing, B] = Right(b) | |
def distRight[C, A, B]: Either[(A, C), (B, C)] => (Either[A, B], C) = | |
either(bimap(left(_), identity(_)), bimap(right(_), identity(_))) | |
def distLeft[C, A, B]: ((Either[A, B], C)) => Either[(A, C), (B, C)] = | |
uncurry(either(curry(left(_)), curry(right(_)))) | |
def curry[C, A, B](f: ((C, A)) => B): C => A => B = c => Function.untupled(f)(c, _) | |
def uncurry[C, A, B](f: C => A => B): ((C, A)) => B = Function.tupled(f(_)(_)) | |
// def choice[A, A1, B, B1](f: A => A1, g: B => B1): Either[A, B] => Either[A1, B1] = ??? | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi there,
Thanks a lot for this nice summarization! While quickly glancing over the first two diagrams, I think that the names of the arrows p1 & p2 need to be switched.
Cheers, Tanju