module Grid exposing (..) import Zipper exposing (..) type alias Grid a = Zipper (Zipper a) {- Basic conversion -} generate : Int -> Int -> (Int -> Int -> a) -> Grid a generate width height gen = let row = Zipper.fromList 1 [2..width] cols = Zipper.fromList 1 [2..height] grid = Zipper.map (\y -> Zipper.map (\x -> (x, y)) row) cols in map (uncurry gen) grid toList : Grid a -> List (List a) toList grid = Zipper.toList <| Zipper.map Zipper.toList <| grid {- Functor like functions -} map : (a -> b) -> Grid a -> Grid b map f grid = Zipper.map (Zipper.map f) grid edit : (a -> a) -> Grid a -> Grid a edit f grid = Zipper.edit (Zipper.edit f) grid {- Comonad functions -} extract : Grid a -> a extract grid = grid.focus.focus -- It was quite difficult to define duplicate. A simple RL.map RL.dup >> RL.dup -- is not the right definition (this would be too simple). With the transpose -- trick it is quite ok to reason about (draw the diagrams yourself!) duplicate : Grid a -> Grid (Grid a) duplicate grid = grid |> Zipper.map Zipper.duplicate |> transpose |> Zipper.map Zipper.duplicate |> transpose extend : (Grid a -> b) -> Grid a -> Grid b extend f w = map f (duplicate w) (=>>) : Grid a -> (Grid a -> b) -> Grid b (=>>) = flip extend {- Domain functions -} shiftLeft : Grid a -> Grid a shiftLeft grid = Zipper.map Zipper.shiftLeft grid shiftRight : Grid a -> Grid a shiftRight grid = Zipper.map Zipper.shiftRight grid shiftUp : Grid a -> Grid a shiftUp grid = Zipper.shiftLeft grid shiftDown : Grid a -> Grid a shiftDown grid = Zipper.shiftRight grid transpose : Grid a -> Grid a transpose grid = let newBefore grid = List.map Zipper.extract grid.before newAfter grid = List.map Zipper.extract grid.after newFocus rl = Zipper (newBefore rl) (extract rl) (newAfter rl) nb = List.map newFocus <| Zipper.iterate1N (List.length grid.focus.before) shiftRight grid nf = newFocus grid na = List.map newFocus <| Zipper.iterate1N (List.length grid.focus.after) shiftLeft grid in Zipper nb nf na getNeighbours : Grid a -> List a getNeighbours grid = [ grid |> shiftLeft |> extract , grid |> shiftUp |> extract , grid |> shiftRight |> extract , grid |> shiftDown |> extract ]