To do IO, you have to be in the IO monad:
printInfo :: Body -> IO Body
printInfo b = do
putStrLn b
return b
And to call this function from within your runSim
function, it to must be inside the IO monad:
runSim :: [Body] -> Integer -> Double -> IO [Body]
(Though there may be better ways of organizing your function.)
This monad business is non-trivial. It is Haskell's greatest strength, but it is difficult to wrap your head around when you first encounter it. I suggest working through a tutorial, such as this one:
Specifically, this will get you started:
http://learnyouahaskell.com/input-and-output
There are many tutorials on monads out there that go into much more detail (writing one is the first thing everyone does after they come to grips with them). The links from haskell.org are your friends.