With PointedGrid[T](pt: (Int, Int), grid: Vector[Vector[Int]]), we have an extract method which uses modular arithmetic to wrap the grid, so that you never access values outside the grid. How do you set up a comonad for a non-wrapping grid? How do you have to change PointedGrid?
One could imagine a world (e.g., if the T type were a monoid) where if the grid index were outside the bounds of the grid, you returned some default value (e.g., the Monoid[T].empty). This makes the PointedGrid actually only a Functor of the sub-category of types which are Monoids, which breaks the rules.
It seems like you might want to try to get past that by not using (Int, Int) as the pointer type in PointedGrid. I guess with dependent types you could encode the appropriate int ranges for the indices. Actually, I'm not really sure what other options there are.
Ah, I guess for the problem at hand (Game of Life) you would change the definition of neighbors to do that checking for you. Then you let extract assume that all points are valid, and don't wrap.
With
PointedGrid[T](pt: (Int, Int), grid: Vector[Vector[Int]])
, we have anextract
method which uses modular arithmetic to wrap the grid, so that you never access values outside the grid. How do you set up a comonad for a non-wrapping grid? How do you have to change PointedGrid?One could imagine a world (e.g., if the T type were a monoid) where if the grid index were outside the bounds of the grid, you returned some default value (e.g., the Monoid[T].empty). This makes the PointedGrid actually only a Functor of the sub-category of types which are Monoids, which breaks the rules.
It seems like you might want to try to get past that by not using (Int, Int) as the pointer type in PointedGrid. I guess with dependent types you could encode the appropriate int ranges for the indices. Actually, I'm not really sure what other options there are.