We explore our first stateful transaction, by devising a means to echo our state value into the resultant for independent modification. With our state value in the resultant, we explore using map
to lift functions into our type as a means to modify the resultant.
In our exploration we find that not only can we change values of the resultant, but we can change the type as needed. We also find that we can combine subsequent map calls into function compositions, allowing us to clean up our code and combine our mappings to avoid excessive interactions with our State
datatype.
To wrap it all up, we take a look at a handy State
construction helper called get
that we can use to query the state into resultant. This allows to read from our state for computations that are based on the value of a given state.
Why is it that the State has a signature State s a
and the function that the constructor takes returns a pair in the opposite order s -> (a, s)
?
@Briisk Very keen observation. The answer is hard to explain as I do not know your understanding of Category Theory. The short version is:
The State Monad is based on how curry and uncurry work together (a -> b -> c
to (a, b) -> c
), it causes the state portion to fall on the right of the Pair
. It also requires the state s
to be fixed to a type for the "maths" to work out. Only the resultant can vary in its type. Because of that, it is common in crocks and many other languages for the Functor portion (the part that can change its type) of an ADT to be on the far right, so for the type siggy, that pushes that to the far right State s a
. s
MUST be fixed and a
can vary its type.
The long, mathy version:
One way State can be explained is with an Adjunction between Set and Set (or in our case, JS and JS), with the Left being a Functor from what I call the resultant (a
) to Pair a s
(with s
being the state type). s
is chosen by the Functor and is fixed to its type, but as it is a Functor the type a
can vary. On Diagrams you may see this functor labeled as (- x S
, with the -
as the varying resultant type)
The reason it is on the right side of the Pair
is because to the Right portion of the Adjunction, back into Set (or JS again in our case). This Functor maps type a
to function s -> a
. So this will map ANY type a
(including a the Pair from above. You will see Diagrams represent this as -^S
, again with the part that varies called -
here.
So if we follow the adjunction by composing the two Functors L(R a) and pick Number
for our s
that will gives us a structure (A x Number)^Number
or a function Number -> Pair A Number
.
@Briisk Very keen observation. The answer is hard to explain as I do not know your understanding of Category Theory.
Thanks a lot for the detailed reply (-: After I posted the question I figured out that it might have something to do with currying but I wanted to be sure about it. This helped to understand it.
Hey, I am curious about your "startsWith" method. I am curious how the seed value is getting into the state prior to you running your compose method. Does crocks flow from "right" to "left". The way it is reading is that I'd expect "startsWith" to be first to plant the "seed", THEN we act on the states value. Since it is last in the chain, I just want to verify it's reading right to left or is their some inner magic going on with crocks?
Hey, I am curious about your "startsWith" method. I am curious how the seed value is getting into the state prior to you running your compose method. Does crocks flow from "right" to "left". The way it is reading is that I'd expect "startsWith" to be first to plant the "seed", THEN we act on the states value. Since it is last in the chain, I just want to verify it's reading right to left or is their some inner magic going on with crocks?
Howdy Dean, thanks for the question! Was this for another lesson? I am having a hard time lining this up with the code presented.
EDIT: Also I do not see startsWith
in this course, do you mean runWith
?