So I wrote my own implementation of StateT because I couldn't get transformers to compile correctly in Haste. I think wanted to get the javascript setInterval working inside my state monad. Here is the ffi call to setInterval.
jsInterval :: Int -> IO () -> IO Int
jsInterval = ffi "(function(t,f){window.setInterval(f,t);})"
I couldn't think of anyway to get the result of m back after it is passed to jsInterval. So I tried to use IORefs.
interval :: Int -> StateT s IO () -> StateT s IO Int
interval i m = StateT $ \s -> do
    ref <- newIORef Nothing
    id_ <- jsInterval i $ do
                       (_, s') <- runStateT m s
                       writeIORef ref (Just s')
    s' <- readIORef ref
    return (id_, s')
This didn't work because it kept the original state. The read happened before the write. So I wrote a function that would poll in a loop until the IORef was written but this just hung forever.
interval :: Int -> StateT s IO () -> StateT s IO Int
interval i m = StateT $ \s -> do
    ref <- newIORef Nothing
    id_ <- jsInterval i $ do
                       (_, s') <- runStateT m s
                       writeIORef ref (Just s')
    s' <- go ref
    return (id_, s')
  where
    go ref = do
      s <- readIORef ref
      case s of
        Nothing -> go ref
        Just s' -> return s'
Is it possible to implement this function? I tried writing an instance of MonadEvent for StateT but that was also unsuccessful.