Sorry :-). I am using Hugs, anything I did wrong ? ------------------------------------------------------------------------------------------------ newtype Parser a = P { parse :: (String -> [(a,String)]) } instance Monad Parser where return v = P (\s -> [(v,s)]) p >>= f = P (\s -> case parse p s of [] -> [] [(v,str)] -> parse (f v) str) fail _ = P (\_ -> []) item :: Parser Char item = Parser (\inp -> case inp of [] -> [] (x:xs) -> [(x,xs)]) p :: Parser (Char,Char) p = do { x <- item ; item ; y <- item ; return (x,y) } -------------------------------------------------- Prelude> :load c:\b.hs [1 of 1] Compiling Main ( C:\b.hs, interpreted ) C:\b.hs:12:7: Not in scope: data constructor `Parser' Failed, modules loaded: none. Prelude> 在 2010年3月19日 下午6:01,Stephen Tetley <stephen.tetley@gmail.com> 写道:
2010/3/19 国平张 <zhangguoping@gmail.com>:
Sorry. The same error, This is new stuff.
Ah indeed - I didn't spot that one as I only read the code rather than ran it.
With the change the parser type to use /newtype/ all the primitive parsers have to be encoded inside the newtype's constructor (primitive parsers being ones that have to look directly at the input stream).
item :: Parser Char item = Parser $ \inp -> case inp of [] -> [] (x:xs) -> [(x,xs)]
Or in a more prosaic style
item :: Parser Char item = Parser (\inp -> case inp of [] -> [] (x:xs) -> [(x,xs)])
This is slightly tiresome. Fortunately once you have defined a small set of primitive parsers, many more parsers can be "derived" by combining the primitives rather than looking at the input stream - this is the power of the monadic style. The p parser you defined with the do ... notation is one such derived parser.
Best wishes
Stephen