Last active
September 30, 2019 21:39
-
-
Save mandubian/dfd670f7740f47a1a2a7b662f828aac6 to your computer and use it in GitHub Desktop.
"Monad is a monoid in the category of endofunctors" evidence using trivial sample of Scala Kind-Polymorphism PoC
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
/** Showing with Kind-Polymorphism the evidence that Monad is a monoid in the category of endofunctors */ | |
object Test extends App { | |
/** Monoid (https://en.wikipedia.org/wiki/Monoid_(category_theory)) | |
* In category theory, a monoid (or monoid object) (M, μ, η) in a monoidal category (C, ⊗, I) | |
* is an object M together with two morphisms | |
* | |
* μ: M ⊗ M → M called multiplication, | |
* η: I → M called unit | |
* | |
*/ | |
trait Monoid[M <: AnyKind, →[_<:AnyKind, _<:AnyKind], ⊗ <: AnyKind, I <: AnyKind] { | |
def η: →[I, M] | |
def μ: →[⊗, M] | |
@inline def unit = η | |
@inline def mult = μ | |
} | |
//////////////////////////////////////////////////////// | |
// Monoid for monomorphic types | |
// | |
trait Monoid1[A] extends Monoid[A, Function1, Tuple2[A, A], Unit] | |
/** Sample with Int & integer multiplication */ | |
object MonoidIntMul extends Monoid1[Int] { | |
val η: Unit => Int = _ => 1 | |
val μ: ((Int, Int)) => Int = { case (a, b) => a * b } | |
} | |
//////////////////////////////////////////////////////// | |
// Monads as monoids | |
// Definition: "Monad is a monoid in the category of endofunctor induced by the composition and the identity functor" | |
// | |
/** Classic functor */ | |
trait Functor[M[_]] { | |
def map[A, B](f: A => B): M[A] => M[B] | |
} | |
/** Functor Morphism (aka Natural Transformation) */ | |
trait ~>[F[_], G[_]] { | |
def apply[A](fa: F[A]): G[A] | |
} | |
/** Id functor */ | |
type Id[A] = A | |
/** Functor Composition */ | |
type Comp[F[_], G[_], A] = F[G[A]] | |
abstract class Monad[M[_]: Functor] extends Monoid[M, ~>, ({type l[t] = Comp[M, M, t] })#l, Id] { | |
// classic point/pure & flatMap/bind encoded using monoid & functor operations | |
def point[A](a: A): M[A] = unit(a) | |
def flatMap[A, B](ma: M[A])(f: A => M[B]): M[B] = mult(implicitly[Functor[M]].map(f)(ma)) | |
} | |
/** Sample with List */ | |
implicit object FunctorList extends Functor[List] { | |
def map[A, B](f: A => B): List[A] => List[B] = l => l.map(f) | |
} | |
object MonadList extends Monad[List] { | |
val η: Id ~> List = new (Id ~> List) { | |
def apply[A](ida: Id[A]) = List() | |
} | |
val μ: ({type l[A] = List[List[A]] })#l ~> List = new (({type l[A] = List[List[A]] })#l ~> List) { | |
def apply[A](ls: List[List[A]]): List[A] = ls.flatten | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment