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

scalaz.Cokleisli.scala Maven / Gradle / Ivy

The newest version!
package org.specs2.internal.scalaz

trait CoKleisli[F[_], A, B] { self =>
  def run(fa: F[A]): B

  def contramapValue[C](f: F[C] => F[A]): CoKleisli[F, C,  B] = new CoKleisli[F, C, B] {
    def run(fc: F[C]): B = self.run(f(fc))
  }

  def map[C](f: B => C): CoKleisli[F, A, C] = new CoKleisli[F, A, C] {
    def run(fa: F[A]) = f(self.run(fa))
  }

  def flatMap[C](f: B => CoKleisli[F, A, C]): CoKleisli[F, A, C] = new CoKleisli[F, A, C] {
    def run(fa: F[A]) = f(self.run(fa)).run(fa)
  }

//  def redaer(implicit i: Identity[A] =:= W[A]): A => B =
//    a => run(id(a))

  def <<=(a: F[A])(implicit F: Functor[F], FC: Cojoin[F]): F[B] =
    F.map(FC.cojoin(a))(run)

  def =>=[C](c: CoKleisli[F, B, C])(implicit F: Functor[F], FC: Cojoin[F]): CoKleisli[F, A, C] =
    CoKleisli(fa => c run (<<=(fa)))

  def compose[C](c: CoKleisli[F, C, A])(implicit F: Functor[F], FC: Cojoin[F]): CoKleisli[F, C, B] =
    c =>= this

  def =<=[C](c: CoKleisli[F, C, A])(implicit F: Functor[F], FC: Cojoin[F]): CoKleisli[F, C, B] =
    compose(c)
}

object CoKleisli extends CoKleisliFunctions with CoKleisliInstances {
  def apply[F[_], A, B](f: F[A] => B): CoKleisli[F, A, B] = new CoKleisli[F, A, B] {
    def run(fa: F[A]): B = f(fa)
  }
}

trait CoKleisliInstances1 {
  implicit def cokleisliArrId[F[_]](implicit F0: Copointed[F]) = new CoKleisliArrId[F] {
    override implicit def F = F0
  }
}

trait CoKleisliInstances0 extends CoKleisliInstances1 {
  implicit def cokleisliCompose[F[_]](implicit F0: Cojoin[F] with Functor[F]) = new CoKleisliCompose[F] {
    override implicit def F = F0
  }
}

trait CoKleisliInstances extends CoKleisliInstances0 {
  implicit def cokleisliMonad[F[_], R] = new CoKleisliMonad[F, R] {}
  
  implicit def cokleisliArrow[F[_]](implicit F0: Comonad[F]) = new CoKleisliArrow[F] {
    override implicit def F = F0
  }
}

trait CoKleisliFunctions {
  // TODO
//  type RedaerT[A, F[_], B] = Cokleisli[F, A, B]
//  type Redaer[A, B] = Cokleisli[Need, A, B]

//  def redaer[A, B](r: A => B): Redaer[A, B] =
//    Cokleisli[A, Identity, B](a => r(a.value))
//
//  def ksa[F[_] : Copointed, A]: Cokleisli[A, F, A] =
//    Cokleisli(a => Copointed[F].copoint(a))
}

trait CoKleisliMonad[F[_], R] extends Monad[({type λ[α] = CoKleisli[F, R, α]})#λ] {
  override def ap[A, B](fa: => CoKleisli[F, R, A])(f: => CoKleisli[F, R, (A) => B]) = f flatMap (fa map _)
  def point[A](a: => A) = CoKleisli(_ => a)
  def bind[A, B](fa: CoKleisli[F, R, A])(f: (A) => CoKleisli[F, R, B]) = fa flatMap f
}


trait CoKleisliArrId[F[_]] extends ArrId[({type λ[α, β] = CoKleisli[F, α, β]})#λ] {
  implicit def F: Copointed[F]

  override def id[A] = CoKleisli(F.copoint)
}

trait CoKleisliCompose[F[_]] extends Compose[({type λ[α, β] = CoKleisli[F, α, β]})#λ] {
  implicit def F: Cojoin[F] with Functor[F]

  override def compose[A, B, C](f: CoKleisli[F, B, C], g: CoKleisli[F, A, B]) = f compose g
}


trait CoKleisliArrow[F[_]]
  extends Arrow[({type λ[α, β] = CoKleisli[F, α, β]})#λ]
  with CoKleisliArrId[F]
  with CoKleisliCompose[F] {

  implicit def F: Comonad[F]

  def arr[A, B](f: (A) => B) = CoKleisli(a => f(F.copoint(a)))

  def first[A, B, C](f: CoKleisli[F, A, B]) =
      CoKleisli[F, (A, C), (B, C)](w => (f.run(F.map(w)(ac => ac._1)), F.copoint(w)._2))
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy