Search code examples
parsinghaskellparsec

Why does runParsecT requires the initial user state twice?


I've defined the following custom parser:

newtype St = St Int
type TxsParser = ParsecT String St (State St)

Now to be able to run this parser, I have to use the runParserT function.

runParserT :: Stream s m t 
           => ParsecT s u m a 
           -> u 
           -> SourceName
           -> s 
           -> m (Either ParseError a) 

Which instantiated to my custom parser reads:

runParserT :: ParsecT String St (State St) a 
           -> St 
           -> SourceName 
           -> String 
           -> State St (Either ParseError a)

But this means that if I want to evaluate the result of runParserT (which is a state monad) I have to supply another initial state (of type St in this case). For instance:

 evalState (runParserT myParser (St 0) fp input) (St 0)

While this works, it seems wrong that I have to repeat the state twice. Does this mean that mixing ParsecT and the State monads is not a good idea?


Solution

  • ParsecT provides state. State provides state. Using both together gives you two independent states.

    You have to initialize both, which is why you see it twice.

    There's nothing wrong with using them together if you want two separate sources of state (e.g. one that backtracks and one that doesn't), but if you only wanted one, this is clearly not what you'd do.