Talk:Haskell/Understanding monads/State

Pedagogy of state
Hello 193.175.53.21,

first of all, thanks a lot for your ongoing contributions! I like the new structure and conciseness of Haskell/Understanding Monads a lot.

Concerning state and the state monad, there is a particular issue: for a lot of things that involve local state, you don't need the state monad at all. For instance, the parenthesis counting function can be implemented as follows:

count inParenthesis []      = 0 count inParenthesis ('(':cs) = count True cs    count inParenthesis (')':cs) = count False cs    count inParenthesis ( c :cs) = (if inParenthesis then 0.5 else 1 ) + count inParenthesis cs

The local state is represented as an accumulating parameter, the pattern  doesn't show up.

Generally, the state monad only makes sense when the state should be implicit, i.e. when you don't want to mention it in the code. So, it should be some kind of global state that would give rise to a lot of needless plumbing when tracked explicitly. Random numbers are an excellent example for this kind of state. (However, they are borderline to being a new monad.)

-- apfe&lambda;mus 09:31, 3 September 2009 (UTC)


 * (I finally decided to get an account; I usually avoid that because it allows me to edit controversial pages, after which I tangle myself up in flamewars).
 * Agreed that the present example is not really great, it's just converting a string to an integer. Also it does not provide for the case in which one extracts values of different types.
 * However I am not sure that random numbers are the best option either. They require people to understand how they work ("random numbers are too important to be left to chance") and how they are implemented in Haskell, so I was looking for something more trivial and came up with a stripped-down parser.
 * Do you have any idea of what would be a simple use of the  monad, requiring little "schooling" (like the section "Random Number Generation")? Or do you think we can cut that section down to a newbie-friendly size? --Orzetto (talk) 07:16, 4 September 2009 (UTC)


 * Yeah, the schooling required for random numbers is quite a drawback. We do have to explain them at some point - they're a recurring topic on the mailing list - but I agree that they're not quite satisfying as introductory example.
 * Concerning examples, let's see how others do it:
 * Wadler introduces the state monad with the task of counting the number of reductions in an interpreter. Interpreters make excellent monad examples - monads are interpreters in a sense - but they might be perceived as impractical. Or rather, unlike nested  (Maybe) or random numbers (State), beginners are unlikely to have written interpreters.
 * Simon Peyton Jones discusses IO in terms of  and, most importantly, shows pictures.
 * Real World Haskell and  uses a stripped down deterministic parser as example, followed by random numbers. The parser requires schooling.
 * All about Monads uses random numbers as example, but forgoes the schooling.
 * Eugene Kirpichov does the same.
 * Ertugrul Söylemez idem.
 * Dan Piponi idem.
 * Overall, looks like the existing options are
 * Going for interpreters, which would have the big advantage of presenting monads in the framework they belong to, at the expense of not being able to connect with what the reader might already know.
 * Random numbers; we have to explain them anyway. In the current text, we can definitely cut down the detailed genesis of (>>=) since that was explained by Haskell/Understanding Monads. The rest can take a cutting, too.
 * Simple parsing. I think it should be possible to come up with a neat example here, but that requires thought. Maybe something along the lines of
 * 
 * -- apfe&lambda;mus 09:28, 4 September 2009 (UTC)
 * -- apfe&lambda;mus 09:28, 4 September 2009 (UTC)


 * Found a criterion for judging examples: the example must contain a function  for some A,S that is reused multiple times.
 * Wadler: ; reuse inside
 * Random numbers: ; reuse for
 * Simple parsing: ; reuse in
 * -- apfe&lambda;mus 09:42, 4 September 2009 (UTC)


 * Hm, if so many use random numbers there may be a good reason (either they copied each other, or it is really the best example). I'll see if I manage to trim down the schooling section a bit. --Orzetto (talk) 17:49, 5 September 2009 (UTC)


 * Found another example that might be suitable, namely the famous turtle from Logo (programming language). In other words, a state machine that supports commands like

forward 100 left 90 right 90 pen up   pen down x <- senseObstruction


 * Paul Hudak did this in his book The Haskell School of Expression with the "Imperative Robot Language".
 * The advantage is of course that the state monad is used to write an interpreter while the drawback is that we have no graphics to show with. (That being said, I always wanted to write some kind of graphics library for use with the wikibook.)
 * -- apfe&lambda;mus 10:23, 8 September 2009 (UTC)

Syntax highlighting bug
There is a syntax highlighting bug (see bug report) which means that single quotes are treated as if they delimit strings. Perhaps the examples should be modified to avoid using single quotes until the bug is fixed.

Questions
Hello there, Is there a place where I can get a little help on this specific chapter? Is there a forum concerning this book or something? I'm having some trouble understanding all this monad stuff and couldn't find any details on the examples of this text. Thank you very much for writing all this, by the way. All the content from beginning through here was very clear and helpful. -- Vitor


 * While not specific to the wikibook, your questions are very welcome on IRC (#haskell), mailing list beginners@haskell.org and StackOverflow.
 * --apfe&lambda;mus 07:29, 28 March 2011 (UTC)

newtype pattern matching
Hello, I noticed what might be an error in following passage:

It says that definition is wrapped inside a newtype to avoid pattern matching, but afaik pattern matching on newtype is possible. Also, is State a typeclass?

I am still novice, so this may be wrong, it would be nice if someone experienced could check this.


 * I guess that by "if we allow it" the author meant "if we export the constructor", from a module that we write on our own. For  /   (which we will in all likelihood not have to define on our own) that is of course the case. I agree the text can be made clearer. As for the by now fixed typeclass issue, it was a mistake - there is a   class, but it has not entered the discussion at this point. --Duplode (discuss • contribs) 04:25, 11 May 2012 (UTC)
 * (By the way, another reason for having  here is that it is a good idea to use it when there is just a single constructor, for efficiency reasons. I will add a note about it in some chapter - it is just a question of deciding the best place.) --Duplode (discuss • contribs) 04:28, 11 May 2012 (UTC)

The Problem with Haskell and State
This section probably had a good intention, but it's thoroughly wooly. First off, it fails to explain "The Problem". Then it says various vague things that may be seen to be somehow related to the advertised topic, if you already know what this section is probably supposed to say.

And there's this: " Procedural languages like C use variables outside the current scope to keep track of state."What? How can variables outside the current scope be used for anything?

And "Starting from an initial state (commonly called the seed), they produce a sequence of numbers that have the appearance of being random." The "they" doesn't refer to anything. It's probably intended to refer to a random number _generator_, in which case the state referred to in a later sentence is a state of that generator object, and not necessarily global per se. Gwideman (discuss • contribs) 10:45, 21 February 2013 (UTC)


 * Fair criticism. I rephrased the introduction slightly and removed the "Problem" header. Re: "outside the current scope", I guess it the intended meaning was "declared outside the current scope", so I changed it to that. As for the final point, I believe it is OK, as local mutable state is no less non-standard in Haskell as mutable globals ("non-standard", of course, only in the sense you need IORefs and the like to pull it off).


 * By the way, possibly the Right Thing to do here would be merging this opening section with the dice examples later on, as they run parallel to each other. Duplode (discuss • contribs) 23:50, 17 August 2013 (UTC)

Processor and processor generator are jargony and hard to grasp
I don't presume there's a better option for terms, but somehow we need better explanation of the words "processor" and "processor generator" to help make sense of them before they get used so much. Backfromquadrangle (discuss • contribs) 06:23, 11 May 2014 (UTC)


 * I never liked those terms either, but I also never managed to find a satisfactory alternative. They aren't even standard jargon. I personally prefer "transition", though I don't think it would be any easier to explain it.
 * By the way, I will apply the second option with respect to the  synonym; as things are it makes the text harder to follow. Actually, the text currently uses the synonym to make a couple of points, so removing it will require a little more thought. Perhaps changing the synonym to something less confusing ( ?  ?  ?) would work.--Duplode (discuss • contribs) 06:54, 11 May 2014 (UTC)


 * Indeed, it isn't a simple thing to change it. It is referenced in spots, and cleaning this up will require some care. I'm not sure what is best. I still don't grasp everything as well with this page because it was more confusing than others to start with. I look forward to seeing your improvements. I've done what I can for now. Backfromquadrangle (discuss • contribs) 06:57, 11 May 2014 (UTC)


 * Currently trying to prune the confusing things. That includes the synonym and the very long names in the bind implementation.--Duplode (discuss • contribs) 09:19, 9 July 2015 (UTC)

Work needed still
As of this comment, I went and consolidated and rearranged everything. I improved bits throughout as I could. Still, this chapter is more confusing than most others. It still has some excessive advanced things and extraneous bits. More work is needed, and I hope others will build on what I did to clean it up further. Backfromquadrangle (discuss • contribs) 06:56, 11 May 2014 (UTC)

rollDie seems overly verbose
Hi, I'm still new to haskell and sorting things out. When I saw the rollDie function

I realized it is just a very verbose way of writing

Am I right? If so, I think this should be mentioned in the text. 193.159.119.251 (discuss) 10:22, 14 August 2014 (UTC)


 * Very much so, and you are completely right. Now fixed (though it still would be better to add a more proper example there).--Duplode (discuss • contribs) 09:17, 9 July 2015 (UTC)

It says that it uses get, put and do notation for illustration. I find it actually pretty crazy code to wrap around my hand with all the things going on under the hood and especially the do notation is a complicated thing that hides a lot. Wouldn't it be good if someone could provide desugared version of this with all the proper (>>=) and lambdas (preserving the use of put and get for illustrative purposes since it may not be very obvious how they fit in)?

Errors in "Introducing State"?
It looks to me like there are many instances of the same error in the "Introducing State" section; namely, the data constructor "State" is not capitalized in code snippets like the one below.

Is that correct? Shouldn't it be the following?

I'm new to Haskell, so I thought I'd ask here instead of just "correcting" it, since I may be missing something.


 * Not a typo. That was explained in a footnote, which I just have moved to the body of the text ("Where did the State constructor go?"). Hope it will be clearer now. Duplode (discuss • contribs) 23:47, 28 June 2015 (UTC)

System.Random stuff may need more explanations
I'm new to Haskell and I'm following the current version of the wikibook from start (sometimes reading other material in parallel). So far, I thought most everything was quite clearly explained. But I had some difficulties following the chapter about "State", in particular concerning the things related to System.Random.

I realize this is not the topic of the chapter, but some details about what "randomIO" and "randomRIO" are, what the "R" stands for in the second, and how they relate to one another would help.

Other questions I have came from this example:

What are these pairs of numbers: "1 1", and "1601120196 1655838864"? What does the "random" function do?

Maybe a comment would be welcome about the "type enforcement" that I guess is happening with ":: (Int, StdGen)": I think this has not often be seen earlier in the book. Bli (discuss • contribs) 10:13, 2 September 2015 (UTC)


 * I the "R" likely stands for "range": while  produces a value within whatever the default range is (for types with a finite number of values like , that typically is the full range of possible values),   allows you to specify the range (in the example we use   to match the sides of a 6-die).
 * is what you get by using  on the generator. It corresponds to the fact that, internally, a   value is just a pair of integers. The algorithms in   use those integers to generate the next (pseudo-)random value.
 * We could broadly describe describe what  does as picking some generator (which might be a   or anything else with a type that is an instance of ), generating a new generator and a new integer from it (using an algorithm implemented through the methods of  ) and converting the generated integer to a value of the type you asked for. If you want to see it with your own eyes, you can have a look at the source of the   module. As you guessed, we'd rather not spend too long discussing the detailed workings of pseudo-random number generation in the text of the chapter; in any case, I will try to find a way to squeeze in some clarifying remarks.
 * On : thanks for spotting that, it was a pretty big oversight! I will add a note about it too; right here might well be a good place to place it.
 * Please keep being vocal about whatever you find confusing :) Feedabck is always very useful. Also, don't be afraid of tweaking stuff you feel that might be improved. Thanks, and cheers, Duplode (discuss • contribs) 01:14, 3 September 2015 (UTC)
 * Please keep being vocal about whatever you find confusing :) Feedabck is always very useful. Also, don't be afraid of tweaking stuff you feel that might be improved. Thanks, and cheers, Duplode (discuss • contribs) 01:14, 3 September 2015 (UTC)

System.Random is no longer a standard library distributed with ghc
It seems that System.Random is no longer distributed with ghc.

I needed to use cabal fetch random and cabal install --lib random before the example would work. The cabal documentation is not novice friendly, and does not make it easy to find how to do a simple fetch and install as opposed to building new packages. The random section needs a bit of explanation on how to install the package.

GeneratorState
This page needs

if it is to allow code snippets to be compiled. Otherwise, refer only to  and the need for the type goes away.

Andro b (discuss • contribs) 09:18, 10 September 2015 (UTC)


 * Thanks for pointing that out. Those occurrences  synonym should have been removed already, so I will do just that. Duplode (discuss • contribs) 03:01, 11 September 2015 (UTC)

Problem with exercise to write instance for
There is an issue with the following exercise which is currently presented in the subsection 'Dice and state'. The exercise is quoted here:

''Write an instance of  for. Your final answer should not use anything that mentions  in its type (that is, ,  , etc.). Then, explain in a few words what the  you wrote does.''

To write an instance, you need the line:

But since  is a type synonym for , the reader needs to enable the   and   language extensions to compile the code (assuming ghc). It is stated at the beginning of the `Introducing State` section that the reader should not be concerned with this.

So, in my opinion, using these language extensions is out of the scope of this tutorial, maybe it should be mentioned in the exercise that the reader will need these extensions, and code should be provided to show how to enable them.

Anyway, I was reading this tutorial because I am learning Haskell myself, so maybe I overlooked something and there is a more obvious way to do the exercise. If so, feel free to ignore my comment. And thank you for this very clear tutorial :)

91.179.126.187 (discuss) 19:03, 15 September 2016 (UTC) Sam


 * You are right in that those extensions are definitely out of scope for this chapter. Ideally, we wouldn't even have to mention them -- I feel that would be an avoidable complication to readers. The unstated assumption of the exercise is that if you are going to try out the instance you wrote you won't be importing the "real"  type (be it from   or  ), which already has a   instance defined, but rather use something like the definition given at the beginning of the "Introducing State" section in your source file. Perhaps that might be made clearer by changing the text of the exercise to "Write an instance of   for   (as defined in the beginning of this section) [...]", but I'm not sure about how helpful that would really be. In any case, thanks for pointing out the issue! --Duplode (discuss • contribs) 03:29, 6 October 2016 (UTC)


 * Using the definitions from above would not work either, since in order for something to be a monad, it must already be an applicative (see https://hackage.haskell.org/package/base-4.9.0.0/docs/Control-Monad.html#t:Monad). And in order for something to be an applicative, it must already be a functor. So the reader would have to define both instances to complete the exercise. Of course, since the monad instance is already given, the applicative instance is trivial. So maybe the exercise could be changed to 'write both an applicative and a functor instance?'. But this might be more difficult than just enabling the language extensions. 81.242.254.229 (discuss) 14:14, 23 October 2016 (UTC) Sam


 * The assumption with respect to that is that the trivial instances of  and   will be written. As things stand, that is pointed out to the readers by the note at the end of Haskell/Understanding monads. Other than duplicating that information here, the only other feasible alternative would be asking readers to write the non-trivial instances − given the current organisation of the book, however, that is better left for the chapter about applicative functors in the Advanced Track. --Duplode (discuss • contribs) 04:11, 25 October 2016 (UTC)

Re-structuring, starting with finite-state machine example
I've had a go at "rewriting" this page (here). I've tried to include all the existing material, but in a different structure. Notably, the random-number stuff comes after a different example based on a finite-state machine for a coin-operated turnstile. I personally find it much easier to follow (but then I guess I would!). I would be very interested to hear what others think, and whether I should replace this page with my proposal (edited/corrected as needed). Thanks.

I've now made the change. The particular problems with the previous version that I've tried to fix include:
 * it's not clear why  is a  . All the examples use   & similar, which only require  ;
 * whilst it's useful to explain random numbers, the state updates already occur within the  & similar functions, so you don't get to see how to write your own state transformations;
 * hence the purpose of  and   are unclear. (I think the "for illustrative purposes" version of   was written to illustrate them, but I think it adds confusion).

There are some other bits I might like to add, if I can work out what to say. Maybe should be in different sections:
 * Can we "encapsulate" somehow (so users can evaluate existing functions e.g.  and , but can't put new states?);
 * monad ≈.
 * State vs ST vs StateT, and "transformer" naming confusion.
 * lazy vs strict State.
 * sequence vs sequenceA vs sequence_ etc.


 * Thank you! Not using random numbers for the initial example is a good idea indeed. I will fully read the rewritten page later. On some of the other bits:


 * monad ≈ : Opinions vary on how helpful that explanation is for understanding  . In any case, there is a brief allusion to it in the   monad chapter, so it might not be necessary to mention it here.


 * Naming confusion: I think that could be addressed by a brief footnote which wouldn't try to explain what  or   are, but would provide links to the relevant chapters elsewhere in the book.


 * Lazy versus strict: That would be an useful thing to mention. I'm just not sure if this chapter is, in the context of the whole book, is the best place to do it. If not here, though, where else? I'm beginning to think it would be worth it to write a new chapter with a more practical bent to supplement the existing ones about laziness and strictness. General discussion about lazy and strict variants of monad transformers and containers could then be done there.


 * vs : Ideally, I would just use   and the other applicative versions (, etc.) everywhere. The other monad chapters aren't written like that, though, which is perhaps something to tidy up.


 * Cheers, Duplode (discuss • contribs) 14:34, 13 February 2021 (UTC)


 * As a beginner who has been struggling to understand the State monad, only finding the annoying random dice example everywhere i looked (with all the shortcomings mentioned above) I have to say that the turnstile section is perfect.
 * It did the trick.
 * It made it click.
 * And to boot, it's slick. 130.76.150.20 (discuss) 11:53, 13 January 2023 (UTC)