His example is intentionally contrived to show a minimal example of StateT. This is who you'd really do it in Haskell:
for strings:
main = repl ""
repl :: String -> IO ()
repl a = getLine >>= \c -> print (a++c) >> repl (a++c)
and it's not that much harder for Ints main = repl 0
repl :: Int -> IO ()
repl a = fmap read getLine >>= \b -> print (a+b) >> repl (a+b)
or using do notation repl a = do $
b <- getLine
print sum
repl sum
where
sum = a + read b
which is still concise and easy to read.