All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scalaz.Kan.scala Maven / Gradle / Ivy

The newest version!
package scalaz

/** The right Kan extension of `H` along `G` */
trait Ran[G[_], H[_], A] { ran =>
  def apply[B](f: A => G[B]): H[B]

  def map[B](f: A => B): Ran[G, H, B] = new Ran[G, H, B] {
    def apply[C](k: B => G[C]): H[C] = ran(f andThen k)
  }

  def toAdjoint[F[_]](implicit A: Adjunction[F, G]): H[F[A]] =
    apply(a => A.unit(a))
}

object Ran {
  import Id._

  implicit def ranFunctor[G[_], H[_]]: Functor[Ran[G, H, *]] =
    new Functor[Ran[G, H, *]] {
      def map[A,B](r: Ran[G, H, A])(f: A => B) = r map f
    }

  /**
   * The universal property of a right Kan extension. The functor `Ran[G,H,_]` and the
   * natural transformation `gran[G,H,_]` are couniversal in the sense that for any
   * functor `K` and a natural transformation `s` from `K[G[_]]` to `H`, a unique
   * natural transformation `toRan` exists from `K` to `Ran[G,H,_]` such that
   * for all `k`, `gran(toRan(k)) = s(k)`.
   */
  def toRan[G[_], H[_], K[_]:Functor, B](k: K[B])(s: λ[α => K[G[α]]] ~> H): Ran[G, H, B] =
    new Ran[G, H, B] {
      def apply[C](f: B => G[C]) = s(Functor[K].map(k)(f))
    }

  /**
   * `toRan` and `fromRan` witness an adjunction from `Compose[G,_,_]` to `Ran[G,_,_]`.
   */
  def fromRan[G[_], H[_], K[_], B](k: K[G[B]])(s: K ~> Ran[G, H, *]): H[B] =
    s(k)(x => x)

  def adjointToRan[F[_], G[_], A](f: F[A])(implicit A: Adjunction[F, G]): Ran[G, Id, A] =
    new Ran[G, Id, A] {
      def apply[B](a: A => G[B]) = A.rightAdjunct(f)(a)
    }

  def ranToAdjoint[F[_], G[_], A](r: Ran[G, Id, A])(implicit A: Adjunction[F, G]): F[A] =
    r(a => A.unit(a))

  def composedAdjointToRan[F[_], G[_], H[_], A](h: H[F[A]])(
    implicit A: Adjunction[F, G], H: Functor[H]): Ran[G, H, A] =
      new Ran[G, H, A] {
        def apply[B](f: A => G[B]) = H.map(h)(A.rightAdjunct(_)(f))
      }

  /** This is the natural transformation that defines a right Kan extension. */
  def gran[G[_], H[_], A](r: Ran[G, H, G[A]]): H[A] =
    r(a => a)
}

/** The left Kan extension of `H` along `G` */
trait Lan[G[_], H[_], A] { lan =>
  type I
  def v: H[I]
  def f(gi: G[I]): A

  /**
   * The universal property of a left Kan extension. The functor `Lan[G,H,_]` and the
   * natural transformation `glan[G,H,_]` are universal in the sense that for any
   * functor `F` and a natural transformation `s` from `H` to `F[G[_]]`, a unique
   * natural transformation `toLan` exists from `Lan[G,H,_]` to `F` such that
   * for all `h`, `glan(h).toLan = s(h)`.
   */
  def toLan[F[_]:Functor](s: H ~> λ[α => F[G[α]]]): F[A] =
    Functor[F].map(s(v))(f)

  /**
   * If `G` is left adjoint to `F`, there is a natural isomorphism between
   * `Lan[G,H,_]` and `H[F[_]]`
   */
  def toAdjoint[F[_]](implicit H: Functor[H], A: Adjunction[G,F]): H[F[A]] =
    H.map(v)(A.leftAdjunct(_)(f))

  def map[B](g: A => B): Lan[G, H, B] = new Lan[G, H, B] {
    type I = lan.I
    private[this] val vc = Need(lan.v)
    def v = vc.value
    def f(gi: G[I]) = g(lan f gi)
  }

}

object Lan extends LanInstances {
  import Id._

  implicit def lanApplicative[G[_]:Functor, H[_]:Applicative]: Applicative[Lan[G, H, *]] =
    new Applicative[Lan[G, H, *]] with LanApply[G, H] {
      def G = implicitly
      def H = implicitly
      def point[A](a: => A): Lan[G, H, A] = new Lan[G,H,A] {
        type I = Unit
        val v = Applicative[H].point(())
        def f(gi: G[I]) = a
      }
    }

  /**
   * `fromLan` and `toLan` witness an adjunction from `Lan[G,_,_]` to `Compose[G,_,_]`:
   */
  def fromLan[F[_], G[_], H[_], B](h: H[B])(s: Lan[G, H, *] ~> F): F[G[B]] =
    s(glan(h))

  /** The natural transformation that defines a left Kan extension */
  def glan[G[_], H[_], A](h: H[A]): Lan[G, H, G[A]] =
    new Lan[G, H, G[A]] {
      type I = A
      val v = h
      def f(gi: G[I]) = gi
    }

  def adjointToLan[F[_], G[_], A](ga: G[A])(implicit A: Adjunction[F, G]): Lan[F, Id, A] =
    new Lan[F, Id, A] {
      type I = G[A]
      val v = ga
      def f(gi: F[I]) = A.counit(gi)
    }

  def lanToAdjoint[F[_], G[_], A](lan: Lan[F,Id,A])(implicit A: Adjunction[F, G]): G[A] =
    A.leftAdjunct(lan.v)(lan.f)

  def composedAdjointToLan[F[_], G[_], H[_], A](h: H[G[A]])(
    implicit A: Adjunction[F, G]): Lan[F, H, A] = new Lan[F, H, A] {
      type I = G[A]
      val v = h
      def f(fi: F[I]) = A.counit(fi)
    }
}

sealed abstract class LanInstances0 {
  implicit def lanFunctor[F[_], G[_]]: Functor[Lan[F, G, *]] =
    new LanFunctor[F, G] { }
}

sealed abstract class LanInstances extends LanInstances0 {
  implicit def lanApply[F[_]: Functor, G[_]: Apply]: Apply[Lan[F, G, *]] =
    new LanApply[F, G] {
      def G = implicitly
      def H = implicitly
    }
}

private trait LanFunctor[G[_], H[_]] extends Functor[Lan[G, H, *]] {
  override final def map[A, B](lan: Lan[G, H, A])(g: A => B) = lan map g
}

private trait LanApply[G[_], H[_]] extends Apply[Lan[G, H, *]] with LanFunctor[G, H] {
  def G: Functor[G]
  def H: Apply[H]

  def ap[A,B](x: => Lan[G, H, A])(xf: => Lan[G, H, A => B]): Lan[G, H, B] = new Lan[G, H, B] {
    val xfp = Need(xf)
    val xp = Need(x)
    override type I = (xfp.value.I, xp.value.I)
    private[this] val vc = Need(H.tuple2(xfp.value.v, xp.value.v))
    def v = vc.value
    def f(gi: G[I]) = xfp.value.f(G.map(gi)(_._1))(xp.value.f(G.map(gi)(_._2)))
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy