Created
May 13, 2019 23:21
-
-
Save lemastero/ae020137746df46338c94ddc56d4f7ce to your computer and use it in GitHub Desktop.
Modular approach to abstractions from Category Theory
This file contains hidden or 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 Wizard.ConstUnit | |
import Wizard.Id | |
import scala.language.higherKinds | |
/* | |
Are there any constructions in Category Theory something like: | |
Given: | |
C category | |
F, G : functors in C | |
M functor category of category C | |
P morphism that map product of any two objects a and b from Category C into object a in M | |
*/ | |
object Wizard { | |
type Id[A] = A // identity functor - what is it in functor category | |
type ConstUnit[A] = Unit // terminal object in functor category | |
type Void[A] = Nothing // initial object in functor category | |
} | |
trait Wizard[F[_], G[_]] { | |
type Spell[_[_], _[_], _, _] // transform 2 type constructors and 2 regular types into sth | |
def doMagic[A, B](f: Spell[F, G, A, B]): F[A] => G[B] | |
} | |
// F F A => B Functor | |
// F F A => F[B] FlatMap | |
// F F F[A] => B CoflatMap | |
// F F F[(A, B)] Zip | |
// F F F[A \/ B] Alt | |
// F F F[A => B] Ap (Apply) | |
// F F F[B => A] Divide | |
// ConstUnit F B Pointed (Pure, Applicative) | |
// ConstUnit Id F[B] CoPointed (CoApplicative) | |
trait Functor[F[_]] extends Wizard[F, F] { | |
type Spell[FF[_], GG[_], AA, BB] = AA => BB | |
// map(fa)(identity) == fa | |
// map(map(fa)(f))(g) == map(fa)(f andThen g) | |
def map[A, B](fa: F[A])(f: A => B): F[B] = doMagic[A, B](f)(fa) | |
} | |
trait FlatMap[F[_]] extends Wizard[F, F] { // Monad | |
type Spell[FF[_], GG[_], AA, BB] = AA => FF[BB] | |
// flatMap(flatMap(fa)(f))(g) == flatMap(fa)(a => flatMap(f(a))(g)) | |
def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B] = doMagic[A, B](f)(fa) | |
} | |
trait Zip[F[_]] extends Wizard[F, F] { // Apply | |
type Spell[FF[_], GG[_], AA, BB] = FF[(AA, BB)] | |
def tuple2[A,B](fa: F[A])(fab: F[(A,B)]): F[B] = doMagic[A,B](fab)(fa) | |
} | |
trait Alt[F[_]] extends Wizard[F, F] { // Alt | |
type Spell[FF[_], GG[_], AA, BB] = FF[Either[AA, BB]] | |
def either2[A, B](fa: F[A])(fab: F[Either[A, B]]): F[B] = doMagic[A,B](fab)(fa) | |
} | |
trait Ap[F[_]] extends Wizard[F, F] { // Apply | |
type Spell[FF[_], GG[_], AA, BB] = FF[AA => BB] | |
def ap[A, B](fa: F[A])(f: F[A => B]): F[B] = doMagic[A, B](f)(fa) | |
} | |
trait Pointed[F[_]] extends Wizard[ConstUnit, F] { // Applicative | |
type Spell[FF[_], GG[_], AA, BB] = BB | |
def pure[B](value: B): F[B] = doMagic(value)(()) | |
} | |
trait CoFlatMap[F[_]] extends Wizard[F, F] { | |
type Spell[FF[_], GG[_], AA, BB] = FF[AA] => BB | |
def extend[A, B](fa: F[A])(f: F[A] => B): F[B] = doMagic[A, B](f)(fa) | |
} | |
trait CoPointed[F[_]] extends Wizard[ConstUnit, Id] { // CoApplicative | |
type Spell[FF[_], GG[_], AA, BB] = FF[BB] | |
def coPure[B](value: F[B]): B = doMagic(value)() | |
} | |
trait Contravariant[F[_]] extends Wizard[F, F] { | |
type Spell[FF[_], GG[_], AA, BB] = BB => AA | |
// contramap(fa)(identity) == fa | |
// contramap( contrampa(fa)(f) )(g) == contramap(fa)(f andThen g) | |
def contramap[A, B](fa: F[A])(f: B => A): F[B] = doMagic[A, B](f)(fa) | |
} | |
trait Divide[F[_]] extends Wizard[F, F] { | |
type Spell[FF[_], GG[_], AA, BB] = FF[BB => AA] | |
def contraAp[A, B](fa: F[A])(f: F[B => A]): F[B] = doMagic[A, B](f)(fa) | |
} | |
// TODO | |
//trait Foldable[F[_]] { | |
// def foldLeft[A, B](fa: F[A], b: B)(f: (B, A) => B): B | |
//} | |
// TODO can we express duplicate and flatten somehow ? | |
// TODO what would happen with when combining different types of F like Id ConstUnit with F[A] => F[B] | |
// a lot of different ways to specify identity (if FF == F and GG == G) | |
// TODO Traversable, Distributive, MonadTrans do not fit this framework | |
// what it tells us about them ? | |
//trait Distributive[F[_], G[_]] extends Wizard[F[G[_]], F[G[_]]] { | |
// type Spell[FF[_], GG[_], AA, BB] = AA => F[BB] | |
// def distribute[G[_], A, B](ga: G[A])(f: A => F[B]): F[G[B]] TODO forall | |
//def distribute[A, B](ga: G[A])(f: A => F[B]): F[G[B]] = doMagic[A,B](f)(ga) :( | |
// def cosequence[G[_], A](ga: G[F[A]]): F[G[A]] | |
//} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment