Storing values in an N x N grid
By defining r = round . sqrt . fromIntegral, newBoard fits on the screen. positions doesn't appear to be used in newboard's first case.

Half the code disappears if we interpret Cell as ((Int, Int), Int).

newBoard's first case can be pushed one recursion call deeper, mapping [] to [] instead of [x] to the current right hand side.

[_] ++ _ should be simplified as _ : _.

positions is only used once, therefore I inline it.

type Cell = ((Int, Int), Int) -- (position, state)

genPositions :: Int -&gt; [(Int, Int)]
genPositions x = [ (a,b) | a &lt;- [0..(x-1)], b &lt;- [0..(x-1)] ]

r = round . sqrt . fromIntegral

newBoard :: Int -&gt; [Int] -&gt; [Cell]
newBoard i [] = []
newBoard i (x : xs) = (genPositions (r i)!!(i - 1 - length xs), x) : newBoard i xs


Successive elements of the list returned by genPositions and xs are zipped together; zip captures this pattern. i is now not needed in its non-rooted form and I recommend changing the interface to take N as an argument instead. Non-square arguments can currently crash !! anyway. genPositions is only used once, therefore I inline it.

type Cell = ((Int, Int), Int) -- (position, state)

newBoard :: Int -&gt; [Int] -&gt; [Cell]
newBoard n = zip $ liftA2 (,) [0..n-1] [0..n-1]


For type Board = Array (Int, Int) Int, Data.Array allows newBoard n = listArray ((0,0),(n-1,n-1)).