Talk:Write Yourself a Scheme in 48 Hours/Parsing

(I hope this is not a bad place to put this comment; this is not very clear from the layout of this discussion page.)

The sentence


 * The first parser must fail before it consumes any input: we'll see later how to implement backtracking.

is perhaps better phrased as:


 * To be actually useful for parsing, the first parse must fail "before" it eats up the input which caused it to fail. Later in the course, we will see how to implement this behaviour using backtracking.

The "must" in the current sentence was confusing to me till I tried, failed --- "wrong" order of arguments to <|> --- and then succeeded at Exercise 2.

GPhilip (discuss • contribs) 08:42, 16 February 2012 (UTC)

2) explicit sequencing with the >>= operator

How in the world are we supposed to do this exercise without any example of how to use >>=?


 * Good point. I suppose Johnathan believed that his explanations of what >>= does, combined with the Haskell report are enough.  Or maybe you're supposed to puzzle through it, and as a result of the struggle, you come out understanding >>= (and consequently monads) pretty well.  If that doesn't work, maybe Haskell/Understanding monads is what you want.  -- Kowey 04:49, 21 August 2006 (UTC)

It would be nice to have a solution to exercise 2) and 3). My solution was to change "x <- many (noneOf "\"")" to "x <- many (parseEscapes)" and defining the function: parseEscapes :: Parser Char parseEscapes = do char '\\'                 oneOf "\"nrt\\" <|> noneOf "\"" I am, however, not sure if this works the right way.


 * I believe there is a slight error in the tutorial at this point. In its current form, it the original parser with "noneOf "\""" matches "hel\\lo", which it obviously shouldn't. I replaced the line with "noneOf ..." with "x <- many ((noneOf "\\\"") <|> ((char '\\') >> (oneOf "\"nrt\\")))", which I believe does the right thing.

Also, if you are testing your Parser, don't forget to escape the escape characters in the String, meaning that if you want to test if "hel\nlo" gets parsed, you should not write readExpr "hel\nlo", because \n will be parsed by the noneOf part, but readExpr "hel\\nlo".

Learning means reading (and lots of it in this case)
From the point of view of a Haskell learner I agree with Kowey 100%.

I've been through the top 10 google results for monads in Haskell (incl. the wikibooks one with waste robots). I'm 1/2 done the gentle tutorial and am on Parsing in the scheme tutorial. The description of monads in this scheme tutorial is both concise and easy to understand for an OO/procedural guy. Though it's only one or two sentences it's fairly insightful.


 * 1) 2 took me a few hours of reading and trying things out (ghc's errors are quite helpful!) to complete the exercise (rewrite parseNumber using do & >>=), but in the end the experience was well worth it. I feel being thrown into the water like that made me understand monads more than anything else I have read so far. I couldn't have done it without the other reading. I had a basic understanding of monads but until using them the 3 different ways I did not see how all the various notations were related. It's surprisingly difficult to find a simple explanation of how you can convert code between the 3 forms (which I should remedy myself, I know update: best explanation I can muster right now).

I'm currently stuck trying to implement #4 R5RS number parsing (#o12345670, #xff, #d987) but I feel in the end when I finally read and experiment enough to figure it out I will have a better understand of something else in Haskell. It's not your average day or two tutorial* this one (not for the average guy like me!). But that complements Haskell which is not your one or two day language, especially for us with little to no previous FP knowledge. Contrast that with moving from Ruby to Python or vice versa, which can be done in a matter of hours for just a basic understanding of the language's syntax and constructs. In procedural languages you really only need to learn syntax (which is often similar) and libraries, which are also somewhat similar.

I guess what I'm saying is that if you're not willing to make the effort to search google (at least) and read many Haskell docs to figure things out then you may want to postpone this tutorial for a little while. There are books on Haskell and imo books are better suited for that sort of initial hand-holding (I'm not too "cool" for books or hand-holding, I just can't afford any CS books right now). --Sjs 20:17, 3 May 2007 (UTC)

(* Let me note that by one or two days I mean the amount of time one can spend on it in 1-2 days, e.g. a couple of hours a day. It'll take me a month or more to spend a full 48 hours on this! I don't know about anyone else.)

Parser fails on booleans
If you feed #t or #f into readExpr it generates an error. parseSymbol should be handling these, but '#' was never put in "symbols" so it doesn't get that far.

The simple solution would be to change "symbols". Alternatively, write a parseBool function and modify parseExpr accordingly (in which case parseSymbol can be simplified):

parseSymbol :: Parser LispVal parseSymbol = do first <- letter <|> symbol rest <- many $ letter <|> digit <|> symbol return $ Symbol $ first:rest

parseBool :: Parser LispVal parseBool = do s <- string "#t" <|> string "#f" return $ case s of   			  "#t" -> Bool True "#f" -> Bool False

parseExpr :: Parser LispVal parseExpr = parseSymbol <|> parseString <|> parseNumber <|> parseBool

Unfortunately, I don't know whether either of those will break the code later, so I figure I'd better not change it myself yet. --Philh 11:16, 4 August 2007 (UTC)


 * I've added it to symbols. It needs to be changed to implement hex, oct and bin numbers, but that's covered in the solution. --Philh 21:46, 4 August 2007 (UTC)

Recognizing floating point numbers
I'm using the pdf version of this book, and as it stands datatypeparser.hs recognizes input such as 3.4 or 3.4.1 (i.e., both floating point input as well as illegal input with more than one decimal point). I'm unable to figure out which parser is currently recognizing these inputs. Has anyone else also faced a similar problem? (Monday, 14th July)

Associativity of function application
Function application associates to the left, not the right:

Debugging tactics
It's kind of hard to see the results of any code at the moment, as the  received by the   function in the case of a successful parse is a LispVal, and AFAICS it hasn't been explained yet how to coerce one of these 'algebraic data types' to a string yet. So there's no way of knowing if your answer to exercise 2 is working, for instance.

Would it be correct to say that we have to write our own version of the show function to do this? This issue is exactly the reason I signed up for wikibooks and read this discussion....the output is too ambiguous. The last time this discussion was edited was February 2011, which makes me think that maybe some poor slob just starting to learn this stuff is going to have to be the one to fix the tutorial. ...d'oh! --Waynr (discuss • contribs) 04:10, 1 February 2012 (UTC)

The parser fails in the following string "\"letters"
I am trying to do exercise 2 from the Parsing section. Where the tutorial asks for extending the parser to support strings that include "\"". I tried it but because I could not find the solution I saw it from the answers. The answer I think is not completely correct because if you give as input "\"letters" the Scheme interpreter fails when it shouldn't. And if you give "letters\"" or "lett\"ers" the interpreter succeeds as it should. Is there any better answer? Thanks 46.246.164.41 (discuss) 08:40, 16 July 2012 (UTC)

Eval needed?
The second set of exercises specifies parsing the backquote. However, the scheme standard indicates that expressions within the backquoted list that are preceded by comma must be evaluated before being added to the resulting list. There is a similar rule for the '@' character, in this case the subsequent expression must evaluate to a list.

So I guess my question is how is one supposed to implement backquote without evaluation? Evaluation is in the next section.

As far as the rest of the tutorial, I've found it to be very challenging! One thing I spent entirely too much time on was the commandline syntax - simply calling the program with the correctly quoted arguments. It took me a while to realize that in order to pass a quoted string to the program, I needed to do this at the bash prompt:

./scheme "\"test string\""

As has been pointed out already, having a 'show LispVal' function early on would be very helpful to knowing whether the parser is working correctly or not. I ended up writing one for that purpose.