Haskell helps to understand this state monad code: where is runState defined?

I am new to Haskell and trying to understand monads. I go through this code. Put it here for quick reference.

newtype State sa = State { runState :: s -> (a,s) } instance Monad (State s) where return a = State $ \s -> (a, s) State act >>= k = State $ \s -> let (a, s') = act s in runState (ka) s' get :: State ss get = State $ \s -> (s, s) put :: s -> State s () put s = State $ \_ -> ((), s) modify :: (s -> s) -> State s () modify f = get >>= \x -> put (fx) evalState :: State sa -> s -> a evalState act = fst . runState act execState :: State sa -> s -> s execState act = snd . runState act 

I did not understand where the runState function is runState . It seems its type is declared in newtype State sa = State { runState :: s -> (a,s) } . The most mysterious part is compiling the code without any errors.

Where is runState indicated? where is his code?

+8
haskell state-monad
source share
2 answers

What you think is missing is the functionality provided by the syntax of the entry. In Haskell, there are several ways to determine the data type. You are probably familiar with statements such as:

 data MyType = MyType String Int 

where the type MyType , which is the type of the sum (i.e., any value of this type has the filled fields String and Int ). If we want to work with this type, we may want to look at the String and Int components separately, so we will define access functions for this:

 getLabel :: MyType -> String getLabel (MyType s _) = s getNum :: MyType -> Int getNum (MyType _ i) = i 

For large data types (with many fields) this can become very tedious, and writing such a function in general is very common: often we have a simple type where the constructor wraps the content, and we want a convenient way to access this content by its own type (that is, without a wrapper).

Because this desire to access fields is so common, Haskell provides syntax for the entry. When you use the write syntax, you essentially name the fields inside the data type, and functions to retrieve the values ​​in these fields are automatically generated. Thus, we can override our data type earlier:

 data MyType' = MyType' { myLabel :: String, myNum :: Int } 

and Haskell automatically generates the access functions myLabel :: MyType' -> String and myNum :: MyType' -> Int . These functions then have the same functionality as the getLabel and getNum functions that we defined earlier.

Take State as an example, we could define it as follows:

 newtype State' sa = State' (s -> (a, s)) 

and wrote a function to access the contents:

 getStateFun :: State' sa -> (s -> (a, s)) getStateFun (State' f) = f 

which will allow us to remove State' "wrapping" from our value. But this is less convenient than using the write syntax that is used in your example: the value stored in the State shell is set by the name of the runState field, and Haskell generates an access function, so the code compiles and runs without a problem. runState then basically does the same thing as getStateFun .

This is also clearly explained in the section “Record Syntax” in this chapter of “Learn You A Haskell For Great Good” .

+6
source share

Yes, you are right, it is defined here:

 newtype State sa = State { runState :: s -> (a,s) } 

basically from a definition like this, you get two functions for free:

  • State :: (s -> (a,s)) -> State sa constructor (named the same as type) - here you can wrap the function in newtype
  • and runState :: State sa -> (s -> (a,s)) (just like State sa -> s -> (a,s) ) inside the syntax of the record - this will end the function from the first argument and apply her to the second argument (or return the back-currying function to work with both interpretations well)

In a sense, you write your code when creating a new State sa value - it will take this value, go to the contents and apply it.

So for example, if you do

 runState get "Hello" { def. get } = runState (State (\s -> (s,s))) "Hello" { apply runState } = (\s -> (s,s)) "Hello" { apply } = ("Hello", "Hello") 

to your question - as far as I understand, the syntax of the entry is equal to this:

 newtype State sa = State (s -> (a,s)) runState :: State sa -> s -> (a,s) runState (State f) s = fs 
+10
source share

All Articles