Skip to content

Instantly share code, notes, and snippets.

@el-hult
Created May 7, 2019 19:37
Show Gist options
  • Save el-hult/85ee08dda0dcf3a2d0f428fe11c1a4ed to your computer and use it in GitHub Desktop.
Save el-hult/85ee08dda0dcf3a2d0f428fe11c1a4ed to your computer and use it in GitHub Desktop.
1D Game of Life in the terminal
-- http://blog.sigfpe.com/2006/12/evaluating-cellular-automata-is.html
-- The above post learned me about this neat comonad instance! :D
data U x = U [x] x [x]
right,left:: U x -> U x -- shift focus of the zipper
right (U a b (c:cs)) = U (b:a) c cs
left (U (a:as) b c) = U as a (b:c)
-- the zipper is a functor
instance Functor U where
fmap f (U a b c) = U (map f a) (f b) (map f c)
class Functor w => Comonad w where
(=>>) :: w a -> (w a -> b) -> w b
coreturn :: w a -> a
cojoin :: w a -> w (w a)
x =>> f = fmap f (cojoin x)
-- the zipper is a comonad
instance Comonad U where
cojoin a = U (tail $ iterate left a) a (tail $ iterate right a)
coreturn (U _ b _) = b
--two alternative rules for the game of life on a boolean zipper
rule1,rule2 :: U Bool -> Bool
rule1 (U (a:_) b (c:_)) = not (a && b && not c || (a==b))
rule2 (U (a:a':_) b (c:c':_)) = (a || c) && (not (a&&c))
shift i u = (iterate (if i<0 then left else right) u) !! abs i
toList i j u = take (j-i) $ half $ shift i u where
half (U _ b c) = [b] ++ c
test = let u = U (repeat False) True (repeat False)
in putStr $
unlines $
take 20 $
map (map (\x -> if x then '#' else ' ') . toList (-20) 20) $
iterate (=>> rule2) u
main = test
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment