19
Oct

Tags: haskelllbachstate monad

In the last installment you may have noticed that there was a lot of state threading in the emitter functions. This involved a lot of careful ordering of s1, s2 etc. which is quickly becoming a problem. Especially so when you aren't consistent with parameter ordering - getLabel took the counter last whilst emitStatment was taking the counter as the first parameter.

It is a misnomer that functional programming cannot have state, rather it cannot have side effects, which is a very different ideal. If you need to maintain state in your application, and a compiler inherently does, then you need to continually pass this state from one function to the next. Conversely, all your functions that modify the state must all return the entire state.

The State Monad was created for instances exactly like this. It defines an explicit interface for passing state from one function to the next, and provides several functions for executing the functions using this state. I'm not going to provide yet another State Monad breakdown - for that I can recommend the following: the official wiki, a great explaination of the mechanics and most recently Learn you a Haskell.

Some things I learned the hard way

The State Monad and Record Syntax

I really struggled with using the State Monad in a situation where multiple peices of state are used. As the compiler is going to need many peices of state such as the label counter, break label, symbol table etc., I started looking for info on record syntax and State Monads. The best I could find was a few paragraphs in Real World Haskell which was pretty clear if brief.

Types for Functions that use the State Monad

Almost all the sample code and tutorials on using the state monad involved no parameters for the functions. All the types where of State s a and almost no examples showed how to pass in extra parameters. Thankfully Learn you a Haskell had some examples that used b -> State s a which lead me to figure out that functions using the State monad can have any type but final type of a function must be State s a and that the type of the function used with runState et.al. must be State s a only. Took me a while to figure this one out.

Random number examples

Annoyingly, 9 times out of 10, any example on the State Monad uses the random number example. This example is next to useless as it neatly ties up the original state in StdGen which hides the actual usage of State. Please try to come up with something original and worthwhile that explains the whole thing. Thanks to Learn you a Haskell, which uses a simple stack example, I was able to figure how and when the State is called.

Simple Example

Rather than try to retro fit the State Monad throughout our emitter in this article, which will be complex and tedious, I will use a simplified example.

First thing we do is create a data type to collect all out stateful information, and a new type using State and our new data type.

-- This will hold all of the data in our state
data EmitStuff = EmitStuff {
    lblCounter :: Int,
    lastLabel :: String 
    } deriving (Show)

-- It is common practice to make your own state type
type MyStateMonad = State EmitStuff 

lblCounter will hold the current count for creating numbered labels, whilst lastLabel will be the last generated label.

Next we will create a function that generates a new label. This will solely use the state to calculate the new label, and then update the state. Do notation makes this much clearer to read.

-- Generates a new label based on the current label counter
-- Stores the generated label, and updates the label counter
newLabel :: MyStateMonad String
newLabel = do 
    st <- get
    let l = "L" ++ show(lblCounter st)
    put st { lblCounter = lblCounter st + 1, lastLabel = l}
    return l

Next we'll create an example that takes an extra parameter. A function that generates a label with a comment.

-- Emits a label followed by a comment 
emitLabelAndComment :: String -> MyStateMonad String
emitLabelAndComment x = do 
    l <- newLabel
    return (l ++ ":  #" ++ x)

Let's take a moment to understand what this one is doing. You'll recall that the State Monad is a wrapper for the type s -> (a, s) which means that the above type signature expands into String -> s -> (String, s). This means that this function will also take the state as input, which is then passed onto newLabel through the State Monads internals. This is a key concept in turning your manual state management code into something that can be used with the state monad. Mike Vanier explains how we can turn the 5 different type of functions using state into one standard format: s -> (String, s).

The next example is calling multiple functions that use state from one function.

-- Simple example showing how we no longer need to manually thread the state when creating labels 
fakeIfStatement :: MyStateMonad String   
fakeIfStatement = do 
    falseBranch <- newLabel
    endLabel <- newLabel
    return ("if not true then \njump " ++ falseBranch ++ "\nDo some true stuff\njump " ++ endLabel ++ "\n" ++ falseBranch ++ ": #some stuff to do if false\n" ++ endLabel) 

Executing the State Monad

Finally we need to tie it all together. The state monad comes with three utility functions for executing the code.

  1. runState returns the result and the state as a tuple
  2. evalState returns the result and discards the state i.e. (result, _) = runState
  3. execState returns the state only and discards the result i.e. (_, state) = runState

Each of these functions take a fucntion of type State s a and an intial state of type s. So first we will create our initial state.

initialState = EmitStuff { lblCounter = 0, lastLabel = "" }

We can then use any of the utility functions to execute our code against this state.

runState fakeIfStatement initialState 
-- or
evalState newLabel initialState

But this is not very useful as the state is reset everytime we apply it to a new function. We have already seen the answer in fakeIfStatement. We simply create one function that executes all the other functions for the duration of the state.

-- Tying it all together 
emitAll = evalState emit EmitStuff { lblCounter = 0, lastLabel = "" } 
    where emit = do
              a <- emitLabelAndComment "This is the first label"
              b <- fakeIfStatement 
              c <- emitLabelAndComment "This is the last label"
              return (a ++ "\n" ++  b ++ "\n" ++ c)

Now if you were to execute putStrLn & emitAll in ghci you will see labels nicely placed and incremented as expected.

You can download and play with all of the above from Github.

Implementing in LBaCH

Implementation into the existing Emitter.Control required a rather large rewrite (94% according to git), but was not terribly difficult. It now reads much clearer and looks a lot more like the BNF notation.

For now I have made the state entry point at the emitBlock level, but in future it may be moved up to encompass the entire emit process.

emitBlock :: Block -> String
emitBlock b = evalState e EmitterData { lblCounter = 0, lastLabel = "" }
    where e = do
              a <- emitBlock' b
              return a 

You can find all the gory details here.


43 comments Bookmark and Share

  1. Avatar for BrandStar Entertainment

    by BrandStar Entertainment - March 7, 2012 11:02 a.m.

    This means that this function will also take the state as input, which is then passed onto newLabel through the State Monads internals.

  2. Avatar for BrandStar Entertainment

    by BrandStar Entertainment - March 7, 2012 11:02 a.m.

    This means that this function will also take the state as input, which is then passed onto newLabel through the State Monads internals.

  3. Avatar for link building

    by link building - May 20, 2012 8:48 p.m.

    "Dofollow" is the natural way of linking. I actually still don't get exactly why numerous blog managers use nofollow option for blog responses. I am a little frustrated because I am starting a blog commenting company and I find quite hard to get great quality dofollow blogs.

  4. Avatar for backpacking tents

    by backpacking tents - May 29, 2012 12:05 p.m.

    Posts like this brgihten up my day. Thanks for taking the time.

  5. Avatar for cheap car insurance quotes

    by cheap car insurance quotes - June 25, 2012 5:39 a.m.

    I was seeking for a great place to get information about comment luv but i think finally i am at the right place so going to take some advantage of your quality writing and nice information .

  6. Avatar for cheapest car insurance quotes

    by cheapest car insurance quotes - June 25, 2012 5:40 a.m.

    I have read your all of the provided information and at the end i agree with your opinion but can you let me now that you offer the cheapest health insurance in the market ?

  7. Avatar for Cheap Health Insurance

    by Cheap Health Insurance - June 25, 2012 5:42 a.m.

    I was seeking for a great place to get my insurance at the affordable rates but i think finally i am at the right place so going to take some advantage of your quality writing and nice information about insurance

  8. Avatar for Cheap Life Insurance

    by Cheap Life Insurance - June 25, 2012 5:42 a.m.

    I have read your all of the provided information and at the end i agree with your opinion but How and where can i get the affordable life insurance ?

  9. Avatar for Cheap Taxi Insurance

    by Cheap Taxi Insurance - June 25, 2012 5:43 a.m.

    I have read your all of the provided information and at the end i agree with your opinion but How and where can i get the Cheapest Auto Insurance?

  10. Avatar for cheap office insurance

    by cheap office insurance - June 25, 2012 5:44 a.m.

    I was seeking for a great place to get information about comment luv but i think finally i am at the right place so going to take some advantage of your quality writing and nice information .

  11. Avatar for cheap home insurance

    by cheap home insurance - June 25, 2012 5:44 a.m.

    You should keep an eye out for more details on this exciting program that will bridge the gap to your highest potential and utmost satisfaction.

  12. Avatar for cheap van insurance

    by cheap van insurance - June 25, 2012 5:44 a.m.

    Think we need to bring more ideas for this purpose. Involvement of young people can be handy in this regard. I am happy to find a good post here. Thank you.

  13. Avatar for cheap 4x4 insurance

    by cheap 4x4 insurance - June 25, 2012 5:45 a.m.

    You should keep an eye out for more details on this exciting program that will bridge the gap to your highest potential and utmost satisfaction.

  14. Avatar for cheap boat insurance

    by cheap boat insurance - June 25, 2012 5:45 a.m.

    Thanks a lot for such a wonderful post, the stuff posted were really interesting and useful. The quality of the content was good and clear. Thanks for the post

  15. Avatar for cheap dog insurance

    by cheap dog insurance - June 25, 2012 5:46 a.m.

    This one is very nicely written and it contains many useful facts. I am happy to find your distinguished way of writing the post. Now you make it easy for me to understand and implement. Thanks for sharing with us.

  16. Avatar for cheap bike insurance

    by cheap bike insurance - June 25, 2012 5:46 a.m.

    it’s really a good write-up, would be interested to read such more informative draft from you ahead, can be a wonderful help to the new readers like me.

  17. Avatar for Chrysler Fifth Avenue Power Steering Rack

    by Chrysler Fifth Avenue Power Steering Rack - July 11, 2012 9:27 a.m.

    Hello! I just would like to give a huge thumbs up for the great info you have here on this post. I will be coming back to your blog for more soon.

  18. Avatar for Shirley Morales

    by Shirley Morales - July 12, 2012 7:46 a.m.

    You write something that people could understand and make the subject intriguing for everyone. I will save this for future use.

  19. Avatar for Auto abbreviations

    by Auto abbreviations - Sept. 22, 2012 10:58 a.m.

    To understand how a clutch works, it helps to know a little bit about friction, which is a measure of how hard it is to slide one object over another. Friction is caused by the peaks and valleys that are part of every surface -- even very smooth surfaces still have microscopic peaks and valleys. The larger these peaks and valleys are, the harder it is to slide the object. You can learn more about friction in

  20. Avatar for Giam gia

    by Giam gia - Nov. 28, 2012 8:57 a.m.

    • I also hope the issue concerns all help. Thank you very much.
  21. Avatar for OBD2 Scanner

    by OBD2 Scanner - Jan. 14, 2013 2:37 a.m.

    Expect you to have a better article to share.Thanks for all your efforts that you have put in this. Thanks for sharing such a wonderful article. AUTO

  22. Avatar for Essay help

    by Essay help - April 3, 2013 1:28 p.m.

    This a comprehensive coverage and a solid tutorial. Thank you for sharing this.

  23. Avatar for Essay help

    by Essay help - April 3, 2013 1:30 p.m.

    First I had some difficulty executing the state monad but thanx for the great help. This a comprehensive coverage and a solid tutorial. Thank you for sharing this.

  24. Avatar for vending machines los angeles

    by vending machines los angeles - April 14, 2013 10:35 a.m.

    I am visiting this site first time & it has awesome information. I have come to know a lot of information after visiting this site. Keep this sort of posting in future as well. I loved reading it and will surely suggest everyone to read it.

  25. Avatar for Toyota Aristo Vertex

    by Toyota Aristo Vertex - May 17, 2013 5:53 a.m.

    Some things in here I have not thought about before.Thanks for making such a cool post which is really very well written.will be referring a lot of friends about this.

  26. Avatar for roksport

    by roksport - May 17, 2013 10:47 a.m.

    nice read, diolch!

  27. Avatar for GTA 5 Free Beta

    by GTA 5 Free Beta - May 22, 2013 9:40 p.m.

    great post GTA 5 Free Beta

  28. Avatar for GTA 5 Free Beta

    by GTA 5 Free Beta - May 22, 2013 9:40 p.m.

    great post GTA 5 Free Beta

  29. Avatar for EQUITY TIPS

    by EQUITY TIPS - June 1, 2013 6:43 a.m.

    very nice post , ilke your way of shareing the post .very usefull infomation in this post you cover all meaningfull points about stocks. really thanks for this posting.

  30. Avatar for mobiles price in India

    by mobiles price in India - June 7, 2013 8:34 p.m.

    The post is nicely written and it contains many good things for me. I am glad to find your impressive way of writing the post. Now it's become easy for me to understand and implement the concept. Thanks for sharing the post. <a href="http://www.bestpriceindia.co.in/">mobiles price in India</a>

  31. Avatar for Android Helova

    by Android Helova - June 8, 2013 4:32 p.m.

    nice article but i dont really undestand that code

  32. Avatar for Kamruzzaman

    by Kamruzzaman - June 17, 2013 7:05 a.m.

    This is a very interesting article.Thank you for this case. <a href="http://webpagedesigncity.com/" title=" best web design "> best web design </a>