module Grid exposing (..) import RingList exposing (..) type alias Grid a = RingList (RingList a) {- Basic conversion -} generate : Int -> Int -> (Int -> Int -> a) -> Grid a generate width height gen = let row = RingList.fromList 1 [2..width] cols = RingList.fromList 1 [2..height] grid = RingList.map (\y -> RingList.map (\x -> (x, y)) row) cols in map (uncurry gen) grid toList : Grid a -> List (List a) toList grid = RingList.toList <| RingList.map RingList.toList <| grid {- Functor like functions -} map : (a -> b) -> Grid a -> Grid b map f grid = RingList.map (RingList.map f) grid edit : (a -> a) -> Grid a -> Grid a edit f grid = RingList.edit (RingList.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 |> RingList.map RingList.duplicate |> transpose |> RingList.map RingList.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 = RingList.map RingList.shiftLeft grid shiftRight : Grid a -> Grid a shiftRight grid = RingList.map RingList.shiftRight grid shiftUp : Grid a -> Grid a shiftUp grid = RingList.shiftLeft grid shiftDown : Grid a -> Grid a shiftDown grid = RingList.shiftRight grid transpose : Grid a -> Grid a transpose grid = let newBefore grid = List.map RingList.extract grid.before newAfter grid = List.map RingList.extract grid.after newFocus rl = RingList (newBefore rl) (extract rl) (newAfter rl) nb = List.map newFocus <| RingList.iterate1N (List.length grid.focus.before) shiftRight grid nf = newFocus grid na = List.map newFocus <| RingList.iterate1N (List.length grid.focus.after) shiftLeft grid in RingList nb nf na