type alias Snake =
{ head : Coordinate
, tail : List Coordinate
}
-- OR
type Snake = Snake Coordinate (List Coordinate)

Note that these are basically custom versions of List.NonEmpty

Math

You could take a completely different approach and never store every segment of the snake. Instead you’d store the position of the head, the length of the snake, and the coordinates of any turns.

type alias Snake =
{ head : Coordinate
, length : Int
, turns : List Coordinate
}

Then you’d use math to figure out if the snake intersects itself. This could make some things easier like lengthening or shortening the snake.

Thank you for your detailed critique. There is one thing I do not understand. In the math section, you propose a different approach, which you call easier for things like growing and shortening the snake.

I think my approach is the simplest and I would consider yours only when handling long snakes would cause performance problems.

The model has growth factor which when positive grows the snake and shrinks the snake when negative. When I cook the model I make sure the growthFactor is decreased towards 0, thus growing and shrinking the snake gradually. If I did not have the uncertain head problems function headBitSnake would be a one-liner. That was my reason for the code like this, but if I have time I will try your suggested approach and will see what happens.

Yeah I don’t know if the math approach is necessarily the best.

You’re essentially trading a storage-based approach for computation-based one. That means you you need to do some more coordinate math but it also means you don’t have to constantly query and update a list of positions. It probably also allows you to avoid invalid states such as a snake with non-consecutive coordinates.

I’ve had good success favoring computation-based approaches but that doesn’t mean they’re always the best solution. It’s up to you to evaluate the tradeoffs.

For the beginner snake game, I will keep my original solution unless I start having performance problems. I will still examin deeper your tip about types.