package scalaz

trait Comonad[W[_]] extends Copointed[W] with Cojoin[W]

trait ComonadLow {
  implicit def comonad[W[_]](implicit j: Cojoin[W], p: Copointed[W]): Comonad[W] = new Comonad[W] {
    def cojoin[A](a: W[A]) = j.cojoin(a)
    def fmap[A, B](a: W[A], f: A => B) = p.fmap(a, f)
    def copure[A](a: W[A]) = p.copure(a)
  }
}

object Comonad extends ComonadLow {
  import Cojoin._
  import Copointed._

  implicit def Tuple2Comonad[A] = comonad[({type λ[α]=(A, α)})#λ](Tuple2Cojoin, Tuple2Copointed)

  import java.util.Map.Entry

  implicit def MapEntryComonad[X] = comonad[({type λ[α]=Entry[X, α]})#λ](MapEntryCojoin, MapEntryCopointed)
}