I wrote a partial implementation of Snake in Haskell. As of now, it only supports the movement of the snake. However, since the code is getting complex, I'm requesting for a review of the code before I add on the food, growing and scoring functions.I'd be glad to hear any suggestions on how this code could be written in a more idiomatic and simpler way (namely, stepSnake and step are long and messy).-- Snake implementation in Haskell.module Snake (    newGame) whereimport Control.Lens (set, ix)import Data.Foldable (toList)import qualified Data.Sequence as S-- Size of the gridn :: Intn = 5data Marking = Empty | Food | Snake    deriving (Show, Read, Eq)type Grid = [[Marking]]emptyGrid :: Int -> GridemptyGrid n = replicate n $ replicate n Emptytype Coord = (Int, Int)data Direction = N | E | W | S    deriving (Show, Read, Eq)stepCoord :: Coord -> Direction -> CoordstepCoord (i, j) dir = case dir of    N -> (i - 1, j)    E -> (i, j + 1)    W -> (i, j - 1)    S -> (i + 1, j)setCoord :: Marking -> Coord -> Grid -> GridsetCoord mark (i, j) grid = set (ix i . ix j) mark gridvalidCoord :: Coord -> BoolvalidCoord (i, j) = i > 0 && j > 0 && i < n && j < ntype Snake = S.Seq CoordnewSnake :: Int -> SnakenewSnake n = S.fromList [c, c', c'']    where c = (n `div` 2, n `div` 2)          c' = stepCoord c E          c'' = stepCoord c' EstepSnake :: Snake -> Direction -> Maybe (Coord, Snake, Coord)stepSnake snake dir = if validCoord tail' && not (tail' `elem` toList snake')                      then Just (head, snake'', tail')                      else Nothing    where (head, snake') = case S.viewl snake of              S.EmptyL -> error snake is empty              x S.:< xs -> (x, xs)          tail = case S.viewr snake of              S.EmptyR -> error snake is empty              _ S.:> x -> x          tail' = stepCoord tail dir          snake'' = snake' S.|> tail'data Game = Game {    grid :: Grid,    snake :: Snake} deriving ShownewGame :: Game newGame = Game {    grid = foldl (flip $ setCoord Snake) (emptyGrid n) (toList snake),    snake = snake} where snake = newSnake nstep :: Game -> Direction -> Maybe Gamestep (Game grid snake) dir = case stepSnake snake dir of    Nothing -> Nothing    Just (head, snake', tail') -> Just $ Game (foldl f grid [(head, Empty), (tail', Snake)]) snake'    where f grid (coord, mark) = setCoord mark coord grid
Snake in Haskell
beginner;game;haskell;snake game
It's a little dangerous to define a top-level constant like n, the name isn't descriptive or distinctive and you end up shadowing it quite a bit. A compiling but incorrect typo is almost inevitable. Since you gave it a definitive comment, why not just give it that name instead? Try defaultGridSize.I can see why you may have used a case statement in stepCoord (to save typing out stepCoord (i, j) repeatedly), but I have a strong preference in the other direction. All pattern-matching which can happen at the top-level generally should.stepCoord :: Coord -> Direction -> CoordstepCoord (i, j) N = (i - 1, j)-- etc...Or you can write a handy little utility function and reorder your arguments to write a point-free function.tuply :: (a -> c, b -> d) -> (a, b) -> (c, d) -- tuple, apply, two ply!tuply (f, g) (a, b) = (f a, g b)stepCoord :: Direction -> Coord -> CoordstepCoord N = tuply (subtract 1, id        )stepCoord E = tuply (id        , + 1       )stepCoord W = tuply (id        , subtract 1)stepCoord S = tuply (+ 1       , id        )Generally all your types should be at the top of the file, i.e. Snake and Game.I might use a list comprehension in writing newSnake to clean it up a little and reduce potential errors from referencing the wrong c('(')) value.newSnake :: Int -> SnakenewSnake boardSize = S.fromList [(mid, j) | j <- [mid .. mid + 2]]  where mid = boardSize `div` 2Right-hand sides composed solely of an if-statement are good candidates for writing guards.stepSnake snake dir    | validCoord tail' && not (tail' `elem` toList snake') = Just (head, snake'', tail')    | otherwise                                            = NothingThis is a very dense function though, I think it might be easier to write if you wrap the version using a Seq snake around a primitive list version. Your snakes will presumably never grow so long as to actually cause a user noticeable slowdown between steps due to list processing, so you might think about tossing out Seq altogether.stepSnake :: Snake -> Direction -> Maybe (Coord, Snake, Coord)stepSnake snake dir = fmap (second fromList) (stepSnakeList (toList snake) dir)  where second f (a, b, c) = (a, f b, c)stepSnakeList :: [Coord] -> Direction -> Maybe (Coord, [Coord], Coord)stepSnakeList snake dir    | validCoord newHead && not (newHead `elem` snake) = Just (oldTail, newSnake, newHead)    | otherwise                                        = Nothing  where    oldTail  = head snake    body     = tail snake    oldHead  = last snake    newHead  = stepCoord oldHead dir    newSnake = body ++ [newHead]Use foldl' from Data.List instead of foldl for newGame and step. Why? It's a long story.