GLUT, its poor reputation intact and justified, is the best I have found.
However, the unhaskellish feeling is not a good reason not to use it. You are at a level below the abstractions you would want to use for a project here. In the same way, you should not use OpenGL because it is deeply entangled with imperative ideas.
But GLUT and OpenGL are fine. The key is to wrap them up into nicer abstractions before using them. I have published to hackage my wrapper for 2D graphics in OpenGL, graphics-drawingcombinators. There are other attempts around, I believe, and I have been out of the graphics game for a while so I am no longer well-versed in the state of the art.
Wrapping up GLUT is a bit harder. IORef
s are no less functional than IO
itself, and to express interactivity while eschewing IO
(and other imperative constructs) you will need some form of FRP. In the end these FRP libraries will end up wrapping imperative ideas underneath them -- when you are dealing with libraries written for C you will not escape this. And it is quite unimportant what lives underneath anyway -- all software has electrical systems of voltages underneath.
Anyway, a couple years ago when I was researching, GLUT was the only library that really worked cross-platform. I prefer the interface of... all the others, but each one only works in certain controlled conditions. That was a major constraint, if you don't share it you might try something else. But the windowing interface is a thin layer that is fairly easily wrapped, you do not need to base any major decisions on this choice.