confusing bit... to make myself learn things I typed out the full type
of the keyboardMouseCallback function:
      
      
(you'll actually do this in production code too! It's a good habit.)
      
            myKeyMouse :: Key -> KeyState -> Modifiers -> Position -> IO ()
and slotted it into the code like so:
    keyboardMouseCallback $= Just myKeyMouse
      
      
Okay -- so here we're seeing that keyboardMouseCallback itself is an IORef:
      
        keyboardMouseCallback :: IORef (Maybe (Key -> KeyState -> Modifiers ->
      
      Position -> IO ()))
Keep in mind also:
      
        ($=) :: IORef a -> a -> IO ()
      
      
      
        In order to be able to pass the "IORef GameState" into the keyboard
handler I have to re-type my keyboardMouseCallback function like so:
    myKeyMouse :: IORef GameState -> Key -> KeyState -> Modifiers ->
Position -> IO ()
and modify the assignment in main to this:
    keyboardMouseCallback $= Just (myKeyMouse gameState)
      
      
Now let's look at the reason it works.
Your types are:
      
        keyboardMouseCallback :: IORef (Maybe (Key -> KeyState -> Modifiers ->
      
      Position -> IO ()))
      
        myKeyMouse :: IORef GameState -> Key -> KeyState -> Modifiers ->
      
      Position -> IO ()
Now, what's the type of the expression `myKeyMouse gameState'? Well,
you've assigned the first argument -- all functions are curried -- so
you get a partial application:
      
        myKeyMouse gameState :: Key -> KeyState -> Modifiers -> Position -> IO ()
      
      
Now you wrap that in Just:
      
        Just (myKeyMouse gameState) :: Maybe (Key -> KeyState -> Modifiers ->
      
      Position -> IO ())
What was the type of keyboardMouseCallback again?
      
        keyboardMouseCallback :: IORef (Maybe (Key -> KeyState -> Modifiers ->
      
      Position -> IO ()))
So the partial application returns a function with the first argument
fixed -- and the resulting function's type is that which is used for the
callbacks.
HTH a little.
A