We take a closer look at the get
construction helper and see how we can use it to lift a function that maps the state portion and updates the resultant with the result. Using get
in this fashion, we then demonstrate how we can make accessors that can then be extended to create more complex interactions.
As there are times that we only want to pull the resultant for a given computation, we take a look at running our instances with the evalWith
method. evalWith
will run our computations, throwing away the state, returning the resultant.
Three videos in and I still have no idea why would anyone use that…
@Dev
Three videos in and I still have no idea why would anyone use that…
There are many uses for it. You can reach for it when you need to combine computations that update or read from some shared state. Think of things like Redux application state or a pure random number generator, or all functions that work on some record type in a database.
When you see that a family of functions (reducers, rng seed, or user records from a database) that need to update or modify a shared state, you typically need to hold that state internally or provide it as a global in a file some where.
In the case of working on say a User record, you may have MANY operations that read from that record type or modify it in some way (changePassword, validatePassword, updateName, getEmail, etc). most of these functions either work on a shared copy or have to pass user
around if you are taking a more functional approach. In these functions there tends to be a lot of destructuring off of the recordType to read from that "state", "restructuring"/merging to update that "state". This can appear all over related functions.
So what State can provide is a means to abstract away all of that state management into a simple pattern that lets your functions just focus on the computation part and not the management. Turns functions like updateName :: String -> User -> User
to only care about the context and not the state, it then becomes updateName :: String -> State User ()
.
This initial course, mostly focuses on what is going on internally with the State datatype, and give an introduction to the API. I am working on a course now as a follow up to this that will demonstrate how to use State
with Redux which will provide more of the Why. This is more the What.
What I miss in this videos so far is a little background information. It has a lot of assumptions that it's clear why the getter functions are called fst
and snd
(Probably first
and second
) but why aren't they named first
and second
then or getState
getValue
.
If one has never heard of crocks
it's also hard to guess what comes in from where.
To me it so far mostly feels like "This is how you follow a recipe" but I miss the explanatory parts that allow to execute upon the presented code.
I think you present it in a good way, just some more clarification about why to do some of the things would be great. <3
@Roman
Sorry about the :corn:fusion there. I kept most of those details out of these lessons because they are more about Pair
then State
, but as State
is a Product Type, we needed to touch on it a bit. I would like to do a course on Pair
as it is an amazing type, so I will more than likely address those bit within that context.
... clear why the getter functions are called fst and snd ...
They come from the names of (2) functions in Haskell, which can be found here. I kept them the same in crocks
.
... (Probably first and second) ...
in crocks first
and second
are methods used on two other types (Arrow
and Star
), you can see their documentation on Arrow
here if you are curious, but I warn you, if you are not familiar with ADTs these may seem super duper :corn:fusing
... but why aren't they named first and second then or getState getValue.
Pair is it's own type, while state
and resultant
/value
are specific meanings for State
. These first few lessons use the "raw" Pair
methods for extraction, but as we progress through the course we will use the State
specific functions evalWith
and execWith
.
... To me it so far mostly feels like "This is how you follow a recipe" but I miss the explanatory parts that allow to execute upon the presented code.
I thought providing all of that context in these lessons would cloud the intent and people would seek out things that they felt were gaps in their understanding. These initial lessons are meant to show the learner what is going on inside of the datatype, and that there is not really any magic going on when we get into some of the other "helper" methods.