
Am Samstag 11 April 2009 19:04:22 schrieb Quentin Moser:
On Sat, 11 Apr 2009 09:37:53 -0700
Michael Mossey
wrote: One other question. Later in the chapter they define peekByte as follows:
-- file: ch10/Parse.hs peekByte :: Parse (Maybe Word8) peekByte = (fmap fst . L.uncons . string) <$> getState
Here they are accessing the 'string' field of the state. So whomever writes this function needs to have the accessor functions. At this point I'm wondering how much state is really getting hidden. Or maybe peekByte would only be written inside the original library.
The point is not so much hiding the state, but hiding the details of the Parse type. newtype Parse a = Parse { runParse :: ParseState -> Either String (a,ParseState) } is, except for the names, StateT ParseState (Either String) a. What peekByte assumes is that there is an instance MonadState ParseState Parse where... , implicitly at least. peekByte won't break if the implementation of Parse is changed, as long as that is maintained. If you look at the haddock docs for Parsec, you'll see that there the State is exposed while GenParser is only exported as an abstract type, allowing the details to be changed if deemed advantageous.
Even before worrying about the accessor functions, a parsing library would in the first place not even export getState, putState, or the ParseState type. It would instead provide functions like parseByte and peekByte as primitives from which all complex parsers will be built.
Parsec does: getParserState setParserState