fmap :: (a -> b) -> [a] -> [b]
traverse :: (a -> IO b) -> [a] -> IO [b]
'traverse' isn't a pariah. You use it to do I/O when you want to do I/O.
f x = x + 1
A function with I/O:
g x = print x $> x + 1
f produces its input plus one.
g does the same but prints the input first.
if you like your I/O you can keep your I/O