I've added a VAO and reduced the inner loop to only a call to glDrawArrays which renders 8000 triangles (24000 vertices). The gameFrame function now benchmarks at ~86ms on my machine. I would expect it to be ~16ms because of vsync. I've pared down the entire project into this buildable cabal project of three files, most of which is OpenGL boilerplate: https://github.com/MichaelBaker/haskell-opengl.