A monad is just a monoid in the category of endofunctors

1

Próbuję zapisać twierdzenie z tytułu jako kod w Scali. Na razie wyszło mi coś takiego:

import scala.language.higherKinds

object MonadIsMonoid {

  trait Monoid[A] {
    def op(a1: A, a2: A): A

    def zero: A
  }

  trait Monad[F[_]] {
    def compose[A, B, C](f: A => F[A])(g: B => F[C]): A => F[C]

    def unit[A](a: => A): F[A]
  }

  def monadToMonoid[A, F[_]](monad: Monad[F]) = new Monoid[A => F[A]] {
    override def op(a1: A => F[A], a2: A => F[A]) =
      monad.compose(a1)(a2)

    override val zero = (a: A) => monad.unit(a)
  }
}

Próba zapisania twierdzenia to metoda monadToMonoid. Jak widać, wrzuciłem tam parametr generyczny A by mi się kompilowało. Skutek jest taki, że przy użyciu monoidu wyprowadzonego z monady typ w monadzie musi być zawsze taki sam, np zawsze musi być Option[Int]. Nie da się złożyć dwóch funkcji z różnymi typami, np URL => Option[String] i String => Option[Int] mimo, iż z użyciem monady bezpośrednio się da.

Możliwości są dwie:

  • twierdzenie z tytułu posta jest nieprecyzyjne (czyli ściślej rzecz biorąc: fałszywe),
  • coś przeoczyłem i jednak da się stworzyć monoid nie tracąc elastyczności monady,

1 użytkowników online, w tym zalogowanych: 0, gości: 1