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.

70 lines
2.2 KiB

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
]