
If you would like to write
let (x,s) = foo 1 [] in let (y,s) = bar x s in let (z,s) = baz x y s in
instead, use a state monad.
Incidentally I did write almost exactly this code once. Ironically, it was meant as a lead-on to the State monad. But there have been other cases where State monad was better avoided. For instance, functions like foo and bar are already written and they are not in the state monad. For example, foo may take a non-empty Set and return the minimal element and the set without the minimal element. There are several such handy functions in Data.Set and Data.Map. Injecting such functions into a Set monad for the sake of three lines seems overkill. Also, in the code above s's don't have to have the same type. I particularly like repeated lets when I am writing the code to apply transformations to it. Being explicit with state passing improves the confidence. It is simpler to reason with the pure code.