Skip to main content

01. ParsecT and Parsec monads

About 2 minHaskellcrashcoursehaskellparsecattoparsectrifecta

01. ParsecT and Parsec monads ๊ด€๋ จ


Megaparsec tutorial > ParsecT and Parsec monads

ParsecT and Parsec monads

ParsecT is the main parser monad transformer and the central data type in megaparsec. ParsecT e s m a is parametrized like this:

  • e is the type of custom component of error messages. If we do not want anything custom (and for now we do not), we just use Void from the Data.Void module.
  • s is the type of input stream. megaparsec works out-of-the-box with String, strict and lazy Text, and strict and lazy ByteStrings. It is also possible to work with custom input streams.
  • m is the inner monad of the ParsecT monad transformer.
  • a is the monadic value, result of parsing.

Since most of the time m is nothing but Identity, the Parsec type synonym is quite useful:

type Parsec e s a = ParsecT e s Identity a

Parsec is simply the non-transformer version of ParsecT.

We can also draw an analogy between the monad transformers in megaparsec and MTL monad transformers and classes. Indeed, there is also the MonadParsec type class which is similar in its purpose to type classes such as MonadState and MonadReader. We will return to MonadParsec later and discuss it in more details.

Speaking of type synonyms, the best way to start writing parser with megaparsec is to define a custom type synonym for your parser. This is a good idea for two reasons:

It will be easier to add top level signatures like Parser Int where Parser is your parsing monad. Without the signatures, things like e will often be ambiguousโ€”it is the flip side of the polymorphic API of the library.

Working with concrete types with all type variables fixed helps GHC optimize a lot better. GHC cannot do much in terms of optimization if your parsers stay polymorphic. Although megaparsec API is polymorphic, it is expected that end user will stick to a concrete type of parsing monad, so inlining and the fact that most functions have their definition dumped into so-called interface files will allow GHC produce very efficient non-polymorphic code.

Letโ€™s define a type synonym (typically called Parser) like this:

type Parser = Parsec Void Text
--                   ^    ^
--                   |    |
-- Custom error component Type of input stream

Until we start dealing with custom parsing errors, when you see Parser in the chapter, assume this type.


์ด์ฐฌํฌ (MarkiiimarK)
Never Stop Learning.