If our definition of ‘stateful’ encompasses every computation that can be massaged into a computation in State
with only some isomorphisms and projections, that covers an awful lot of computations.
Consider that the Kleisli arrow in State
is a -> s -> (s, b)
. Flipped and uncurried, that’s (s, a) -> (s, b)
. Up to isomorphism, State
composition is merely function composition. Basically, any function whose domain and codomain are both isomorphic to product types with a common, non-trivial factor is ‘smuggling state’.
I wonder if a more useful definition of ‘statefulness’ is a measure of how much of your (s, a) -> (s, b)
computation is made out of second (f :: a -> b)
and how much of it actually uses the common s
. The essence of a ‘stateful’ computation is that most of it doesn’t explicitly handle s
; the state lurks in the background, unnoticed, causing problems for people who try to do equational reasoning on the pure component without taking the state component into account. The more that s
is explicitly handled, the less ‘stateful’ I consider the computation to be. (Somewhat paradoxically, this defines the extreme where s
is ignored entirely as ‘the most stateful’, which is maybe not great.)