Programming in Scala”
fpiscompanion
fpiscompanion
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
Chapter notes 36<br />
counit is pronounced “co-unit”, not “cow-knit”.<br />
We say that F is left adjo<strong>in</strong>t to G, written F ⊣ G <strong>in</strong> mathematical notation.<br />
There are two laws of adjunctions:<br />
1. counit(F.map(x)(unit)) == x<br />
2. G.map(unit(x))(counit) == x<br />
Another way to view an adjunction is that there is an isomorphism between the types F[A] => B<br />
and A => G[B]:<br />
def leftAdjunct[A,B](k: F[A] => B): A => G[B] =<br />
a => G.map(unit(a))(k)<br />
def rightAdjunct[A,B](k: A => G[B]): F[A] => B =<br />
fa => counit(F.map(fa)(k))<br />
An adjunction has the property that G[F[_]] is a monad:<br />
def jo<strong>in</strong>[A](g: G[F[G[F[A]]]]): G[F[A]] =<br />
G.map(g)(counit)<br />
def map[A,B](g: G[F[A]])(f: A => B): G[F[B]] =<br />
G.map(F.map(f))<br />
def flatMap[A,B](g: G[F[A]])(f: A => G[F[B]]): G[F[B]] =<br />
jo<strong>in</strong>(map(g)(f))<br />
For example, the State monad is formed by the adjo<strong>in</strong>t functors (_, S) and S => _.<br />
In fact, every monad is formed by an adjunction.<br />
Comonads<br />
Dually¹⁵⁴, the composite functor F[G[A]] is a comonad¹⁵⁵. A comonad is exactly like a monad, except<br />
the direction of the function arrows is reversed:<br />
trait Comonad[F[_]] {<br />
}<br />
def counit[A](a: F[A]): A<br />
def extend[A,B](a: F[A])(f: F[A] => B): F[B]<br />
Instead of a unit that goes from A to F[A], we have a counit that goes from F[A] to A. And <strong>in</strong>stead<br />
of a flatMap that takes a function of type A => F[B], we have extend that takes a function go<strong>in</strong>g<br />
the other way: F[A] => B.<br />
A simple example of a comonad is the reader comonad:<br />
¹⁵⁴http://en.wikipedia.org/wiki/Dual_%28mathematics%29<br />
¹⁵⁵http://docs.typelevel.org/api/scalaz/stable/7.1.0-M3/doc/#scalaz.Comonad