Lay González
Lay González

Reputation: 2985

Am I missing something fundamental about the State Monad? Why keep state and input separately?

Why our functions need to take a state and an input and not just a state that includes the input (or an input that includes the state?).

I assume that you might want to apply different inputs with the same state and therefore you want to keep them separately, but is that the only reason?

I feel that I'm missing something fundamental, but I can't grasp it.

Upvotes: 2

Views: 146

Answers (4)

haroldcarr
haroldcarr

Reputation: 1575

Terminology: if you are new to Haskell it is easy to get confused/fooled by statements like "State data is mutable". Someone coming from imperative programs might take "mutable" to mean change the value in an existing location. For some parts of Haskell (e.g., IORef) that is indeed true. In the State monad case it is not true.

State supports mutating a state into a NEW state - the new state is completely independent of the old state. Nothing is mutated in place.

Sometimes this is called "effectful" programming - you get the benefits of effects but without using "real" side-effects - State is completely pure.

Upvotes: 0

Nikita Volkov
Nikita Volkov

Reputation: 43309

I'm not entirely sure what your actual question is but here are some facts that could probably answer it:

  1. State data is mutable (via the State monad), input data is immutable. In Haskell it's conventional to achieve maximum of type-level safety. If you unite input with state you'll make it mutable too for no purpose.

  2. Monads do not have inputs. You might be thinking about arrows. And in fact there is a state arrow.

Upvotes: 1

Daniel
Daniel

Reputation: 27549

The State monad is useful because it enforces a pattern which is obvious from the type.

Instead of having every function in your code look like:

foo state x y = ... return (state', z)

you can use State to make clear what your intent is.

Upvotes: 0

Yuriosity
Yuriosity

Reputation: 1918

That's due to the conveniency. In general, separate arguments, if they are conceptually separated (I mean, they aren't properties of a single object, for example), are better than packed in a datatype, because in the former case you can use currying, combinators and other advantages of functional approach.

Without monads, each stateful function would look like foo :: b -> s -> (s, a), and with monads, we can extract the common part, name it: newtype State s a = State (s -> (s, a)), and define return and >>= for it. Moreover, any simple function bar :: a -> b can be easily turned into a stateful via a simple change of the result: bar :: a -> State s b. That would be impossible if both input and state were carried in a single argument (say, a tuple: foo :: (s, a) -> (s, a).

Upvotes: 1

Related Questions