Skip to content

Latest commit

 

History

History
121 lines (95 loc) · 6.81 KB

Comonads.MD

File metadata and controls

121 lines (95 loc) · 6.81 KB

Comonad

Abstraction for type with one hole that allows:

  • map over (extends Functor)
  • get current value
  • duplicate one layer of abstraction It is dual to Monad (Monad allow to put value in and collapse one layer).
trait CoflatMap[F[_]] extends Functor[F] {
  def coflatMap[A, B](fa: F[A])(f: F[A] => B): F[B]
}

trait Comonad[C[_]] extends CoflatMap[C] {
  def extract[A](ca: C[A]): A // counit
  def duplicate[A](ca: C[A]): C[C[A]] // coflatten
  def extend[A, B](ca: C[A])(f: C[A] => B): C[B] = map(duplicate(ca))(f) // coflatMap, cobind
}

If we define extract and extend:

  1. fa.extend(_.extract) == fa
  2. fa.extend(f).extract == f(fa)
  3. fa.extend(f).extend(g) == fa.extend(a => g(a.extend(f)))

If we define comonad using map, extract and duplicate: 3. fa.duplicate.extract == fa 4. fa.duplicate.map(_.extract) == fa 5. fa.duplicate.duplicate == fa.duplicate.map(_.duplicate)

And if we provide implementation for both duplicate and extend: 6. fa.extend(f) == fa.duplicate.map(f) 7. fa.duplicate == fa.extend(identity) 8. fa.map(h) == fa.extend(faInner => h(faInner.extract))

The definitions of laws in Cats src Comonad , Cats src Coflatmap and Haskell Control.Comonad.

  • Derived methods:
 def extend[A, B](ca: C[A])(f: C[A] => B): C[B] = map(duplicate(ca))(f) // coFlatMap

Method extend can be use to chain oparations on comonads - this is called coKleisli composition.

  • Implementations of comonad can be done for: None empty list, Rose tree, Identity

  • Resources

    • Scala Comonad Tutorial, Part 1 - Rúnar Bjarnason (blog post)
    • Scala Comonad Tutorial, Part 2 - Rúnar Bjarnason (blog post)
    • Streams for (Co)Free! - John DeGoes: (video)
    • Life Is A Comonad - Elias Jordan (video) (blog post) (reddit)
    • Conway's Game Of Life Using Representable And Comonads - Chris Penner (blog post)
    • (Haskell) Getting a Quick Fix on Comonads - Kenneth Foner (video)
    • Haskell libraries using Comonads
    • (Haskell) Monads from Comonads - Edward Kmett (blog post)
    • (Haskell) Monad Transformers from Comonads - Edward Kmett (blog post)
    • (Haskell) More on Comonads as Monad Transformers - Edward Kmett (blog post)
    • (Haskell) The Cofree Comonad and the Expression Problem - Edward Kmett (blog post)
    • (Haskell) Comonads as Spaces - Phil Freeman (blog post)
    • (Purescript) PS Unscripted - Comonads for UIs - Phil Freeman (video)
    • A Real-World Application with a Comonadic User Interface - Arthur Xavierpdf
    • (Haskell) Cofun with cofree comonads - Dave Laing (slides, video, code)
    • (Haskell) matchingSub is Comonadic (obviously!) - geophf blog post
    • (Haskell) Realized Constants are Comonadic - geophf blog post

Coreader (Env comonad, Product comonad)

Wrap value of type A with some context R.

case class CoReader[R, A](extract: A, ask: R) {
  def map[B](f: A => B): CoReader[R, B] = CoReader(f(extract), ask)
  def duplicate: CoReader[R, CoReader[R, A]] = CoReader(this, ask)
}

Cowriter

It is like Writer monad, combines all logs (using Monid) when they are ready.

case class Cowriter[W, A](tell: W => A)(implicit m: Monoid[W]) {
  def extract: A = tell(m.empty)
  def duplicate: Cowriter[W, Cowriter[W, A]] = Cowriter( w1 =>
    Cowriter( w2 =>
      tell(m.append(w1, w2))
    )
  )
  def map[B](f: A => B) = Cowriter(tell andThen f)
}
  • Resources
    • Scala Comonad Tutorial, Part 1 - Rúnar Bjarnason (blog post)

Bimonad

Combine power of Monad and Comonad with additiona laws that tie together Monad and Comonad methods

trait Bimonad[T] extends Monad[T] with Comonad[T]
  • They simplify resolution of implicits for things that are Monad and Comonad

Resources: