POETICS COPOETICS Degree Degree Financial Security Financial Security (AKA PROGRAMMING) ✴ ✴ “You cannot get the news from poems yet men die every day for lack of what is found there” - W.C.W.
METHODOLOGY PRAXIS ▸ Theory motived by doing ▸ Look at a data type with a comonad instance ▸ Understand why it might be useful ▸ Application of comonads in Conway’s game of life
def coflatMap[A,B](x: F[A])(f: F[A] => B): F[B] = map(coflatten(x))(f) COMONAD F[_] HAS A FUNCTOR SO WE CAN MAP OVER OUR DUPLICATED STRUCTURE AND APPLY f
COMONAD INSTANCE FOR ZIPPERS ▸ The focus allows us to call extract ▸ Coflatten creates a Zipper of all possible Zippers ▸ Every element is in focus once
def duplicateLefts[B]: Stream[Zipper[A]] = unfold(this)((z: Zipper[A]) => z.maybeLeft.map((x: Zipper[A]) => (x, x)) ) COMONAD INSTANCE FOR ZIPPERS FROM THIS ZIPPER, WE’RE BUILDING A STREAM…
CONWAY’S GAME OF LIFE THE RULES ▸ A live cell with two or three neighbors stays alive ▸ A dead cell with three live neighbors becomes a live cell ▸ All other live cells die in the next generation
LIFECYCLE WE NEED A FUNCTION THAT… ▸ Takes in the current grid ▸ Allows us to get the neighborhood of a focus ▸ Apply the rules for the game ▸ Returns a grid
def cellLifecycle(grid: GridZipper[Int]): Int = { val neighborList: List[Int] = grid.getNeighbors (neighborList.sum, grid.extract) match { case (sum, 1) if sum == 2 || sum == 3 => 1 case (3, 0) => 1 case (_, 1) => 0 case (_, x) => x } } MODEL THE RULES DEAD CELL = 0 ALIVE CELL = 1
def cellLifecycle(grid: GridZipper[Int]): Int = { val neighborList: List[Int] = grid.getNeighbors (neighborList.sum, grid.extract) match { case (sum, 1) if sum == 2 || sum == 3 => 1 case (3, 0) => 1 case (_, 1) => 0 case (_, x) => x } } MODEL THE RULES
def cellLifecycle(grid: GridZipper[Int]): Int = { val neighborList: List[Int] = grid.getNeighbors (neighborList.sum, grid.extract) match { case (sum, 1) if sum == 2 || sum == 3 => 1 case (3, 0) => 1 case (_, 1) => 0 case (_, x) => x } } MODEL THE RULES
def cellLifecycle(grid: GridZipper[Int]): Int = { val neighborList: List[Int] = grid.getNeighbors (neighborList.sum, grid.extract) match { case (sum, 1) if sum == 2 || sum == 3 => 1 case (3, 0) => 1 case (_, 1) => 0 case (_, x) => x } } MODEL THE RULES
def cellLifecycle(grid: GridZipper[Int]): Int = { val neighborList: List[Int] = grid.getNeighbors (neighborList.sum, grid.extract) match { case (sum, 1) if sum == 2 || sum == 3 => 1 case (3, 0) => 1 case (_, 1) => 0 case (_, x) => x } } MODEL THE RULES CELL IS ALIVE, 2 OR 3 NEIGHBORS STAY ALIVE
def cellLifecycle(grid: GridZipper[Int]): Int = { val neighborList: List[Int] = grid.getNeighbors (neighborList.sum, grid.extract) match { case (sum, 1) if sum == 2 || sum == 3 => 1 case (3, 0) => 1 case (_, 1) => 0 case (_, x) => x } } MODEL THE RULES 3 ALIVE NEIGHBORS CELL BECOMES ALIVE
def cellLifecycle(grid: GridZipper[Int]): Int = { val neighborList: List[Int] = grid.getNeighbors (neighborList.sum, grid.extract) match { case (sum, 1) if sum == 2 || sum == 3 => 1 case (3, 0) => 1 case (_, 1) => 0 case (_, x) => x } } MODEL THE RULES ALL OTHER CASES, AN ALIVE CELL DIES
def cellLifecycle(grid: GridZipper[Int]): Int = { val neighborList: List[Int] = grid.getNeighbors (neighborList.sum, grid.extract) match { case (sum, 1) if sum == 2 || sum == 3 => 1 case (3, 0) => 1 case (_, 1) => 0 case (_, x) => x } } MODEL THE RULES DEAD CELLS STAY DEAD
def generation(grid: GridZipper[Int]): GridZipper[Int] = { grid.coflatMap(cellLifecycle) } MODEL THE GENERATION TAKES OUR CELL LIFECYCLE FUNCTION AND EXTENDS IT OVER THE ENTIRE GRID!
THINGS WE KNOW ▸ Comonads for context dependent computations ▸ Monads as context producing ▸ Zippers are one example of a comonadic data structure ✴ Which is to say …
POSTSCRIPT ▸ Link to source code: https://github.com/rlmark/ comonadic_life ▸ Link to blog post about this code: https://www. 47deg.com/blog/game-of-life-scala/ ▸ Stuck in the middle with you… https:// personal.cis.strath.ac.uk/conor.mcbride/Dissect.pdf ▸ OG Zippers: https://www.st.cs.uni-saarland.de/edu/ seminare/2005/advanced-fp/docs/huet-zipper.pdf