Cellular automata in Elm
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

62 lines
2.1 KiB

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