Skip to content

Instantly share code, notes, and snippets.

@shkesar
Created July 15, 2019 18:25
Show Gist options
  • Save shkesar/3067eff58d643657c738129dd36de0c3 to your computer and use it in GitHub Desktop.
Save shkesar/3067eff58d643657c738129dd36de0c3 to your computer and use it in GitHub Desktop.
Comonads
trait Functor[F[_]] {
def map[A,B](fa: F[A])(f: A => B): F[B]
}
// For lifting pure values into effects and to chain effects
trait Monad[F[_]] extends Functor[F] {
def pure(x: A): F[A]
def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B]
// map can now be defined in terms of pure and flatten so Monad is a functor
}
trait Comonad[F[_]] extends Functor[F] {
def extract(x: F[A]): A
def coflatMap[A, B](fa: F[A])(f: F[A] => B): F[B]
def coflatten[A](fa: F[A]): F[F[A]]
// map can be defined in terms of coflatMap and extract
}
import cats.Comonad
case class FocusedGrid[A](focus: Tuple2[Int,Int], grid : Vector[Vector[A]])
implicit val focusedGridComonad = new Comonad[FocussedGrid] {
override def map[A,B](fa: FocusedGrid[A])(f: A => B): FocusedGrid[B] =
FocusedGrid(fa.focus, fa.grid.map(row => row.map(a => f(a))))
override def coflatten[A](fa: FocusedGrid[A]): FocusedGrid[FocusedGrid[A]] = {
val grid = fa.grid.mapWithIndex((row, ri) =>
row.mapWithIndex((col, ci) =>
FocussedGrid((ri, ci), fa.grid)))
FocusedGrid(fa.focus, grid)
}
override def coflatMap[A, B](fa: FocusedGrid[A])(f: FocusedGrid[A] => B): FocusedGrid[B] = {
val grid = coflatten(fa).grid.map(_.map(col => f(col)))
FocusedGrid(fa.focus, grid)
}
override def extract[A](fa: FocusedGrid[A]): A = fa.grid(fa.focus._1)(fa.focus._2)
}
// Image Manipulation can be done using FocusedGrid
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment