Curious what people think about this implementation of Conway's Game of Life in Haskell.
{-# LANGUAGE QuasiQuotes #-}
module Test.Conway (
conwayCalculateAge,
conwayStep,
conwayMakeRandom,
conwayMakeRandomIO,
conwayMakeEmpty
) where
import Data.Array.Repa
import Data.Array.Repa.Stencil
import Data.Array.Repa.Stencil.Dim2
import Data.Functor.Identity
import System.Random
conwayNeighborsStencil :: Stencil DIM2 Int
conwayNeighborsStencil =
[stencil2| 1 1 1
1 0 1
1 1 1 |]
conwayStep :: Array U DIM2 Int -> Array U DIM2 Int
conwayStep r =
runIdentity . computeP . szipWith rules r . -- Apply rules
mapStencil2 (BoundConst 0) conwayNeighborsStencil $ r -- Find # neigbors
where
rules 1 2 = 1 -- Alive and has two neighbours
rules _ 3 = 1 -- Alive or dead and has three neighbours
rules _ _ = 0 -- All others are dead
conwayMakeRandom :: RandomGen g => g -> DIM2 -> Array U DIM2 Int
conwayMakeRandom g sh =
fromListUnboxed sh $ take (size sh) $ randomRs (0, 1) g
Naturally, conwayMakeRandom
creates the initial grid and conwayStep
advances the evolution a grid.
1 Answer 1
That's a nice use of stencil2
and Repa. All in all there isn't much to review, it follows a common approach on Conway's Game of Life with Repa. No type signatures are missing, but with Repa it's more or less mandatory to add them.
Well done. But the next time, consider adding all your code, conwayCalculateAge
and conwayMakeEmpty
were probably interesting (I suspect conwayMakeRandomIO
to be the same as conwayMakeRandom
but using randomRIOs = randomRs (0, 1) <$> newStdGen
).