

Graham Klyne GK at ninebynine.org
Fri Jun 25 06:30:37 EDT 2004

At 15:17 24/06/04 +0300, Max Ischenko wrote:


>>The HaXml XML parser has a separate lexer, but it turns out that it's not 
>>always easy to get the tokenization right without having contextual 
>>information (e.g. from the syntax analyzer).
>>(XML is rather messy in that way.)
>Well, yes. In Markdown, like in most other "rich-text" formats symbols
>are overloaded a lot. After all, it has to constrain itself to "plain text".
>I'm going to try a "two-stage tokenization" (not sure how to name this 
>correctly). Basically, first I'd split the raw text into "symbols" (like 
>space, char, digit, left-bracket) and then turn these symbols into tokens 
>(like paragraph, reference, start bold text, end bold text, etc.)

Maybe that can work.  But in raw text, as opposed to markup, some 
characters get treated differently.  The XML lexer I mentioned aims to 
distinguish "free text" from markup and other formal structure, and returns 
arbitrarily long sections of free text as a single token.


>>The outline sketched above has at least one weakness, it doesn't provide 
>>any way to handle errors.  This could be overcome by using Either as an 
>>error monad (see Control.Monad and Control.Monad.Error in the standard 
>>hierarchical libraries), and then using >>= in place of function 
>>composition (noting the reversal of component order):
>Uhm. Looks like error handling is very different from the imperative 
>languages. I think I'll try to get the basic version without it first. On 
>a related note, how can I debug my program along the way? I suspect I 
>can't even use a print inside a function.
>[ error handling cut ]
>>Just to check out my use of >>= and do-notation, I constructed a trivial 
>>complete program using both.
>Not sure how much time it will take to comprehend this "triviality".
>I'm not yet can grasp the monads and their applications.

Using it is easy enough.  In this case, when any component returns a (Left 
x) value (an error), that is propagated down the pipeline without further 
processing.  But the (y) in a (Right y) is passed to the next component for 

Fully understanding how monads work takes a little longer.  It's an 
abstract idea that serves a surprising number of practical requirements.

The issue you come up against in a functional language is that there's no 
way to "bale out" if you see an error, other than by aborting the program 
altogether, by returning (error x), or by treating the error condition as 
part of the return value and testing it at each stage.  The monad machinery 
allows all that result-testing to be tucked away in the bind (>>=) operator.

(There is a third way that involves catching exceptions, but that only 
works in the IO monad.  There's a recent thread about that on the [Haskell] 
mailing list, subject "IO, exceptions and error handling".)


>[ example skipped ]
>Thank you for your time and explanations. It were surely very helpful, 
>esp. considering the fact I had exactly one reply to my post. ;-)
>Haskell-Cafe mailing list
>Haskell-Cafe at haskell.org

Graham Klyne
For email:

More information about the Haskell-Cafe mailing list