package scalaz trait Cokleisli[W[_], A, B] { def apply(a: W[A]): B import Scalaz._ def <<=(a: W[A])(implicit w: Comonad[W]): W[B] = a =>> apply def =>=[C](c: Cokleisli[W, B, C])(implicit b: Comonad[W]): Cokleisli[W, A, C] = ★(e => c(e =>> (Cokleisli.this(_)))) def =>=[C](c: W[B] => C)(implicit b: Comonad[W]): Cokleisli[W, A, C] = =>=(★(c)) def =<=[C](c: Cokleisli[W, C, A])(implicit b: Comonad[W]): Cokleisli[W, C, B] = c =>= this def =<=[C](c: W[C] => A)(implicit b: Comonad[W]): Cokleisli[W, C, B] = ★(c) =>= this } trait Cokleislis { def ★[W[_], A, B](f: W[A] => B): Cokleisli[W, A, B] = new Cokleisli[W, A, B] { def apply(a: W[A]) = f(a) } def cokleisli[W[_], A, B](f: W[A] => B): Cokleisli[W, A, B] = ★(f) }