Composable Parsers with Attoparsec
May 6, 2025
I’ve been diving into Haskell’s attoparsec and I’m impressed by how it simplifies building complex parsers. Here’s a quick example for a DSL snippet like "name=Some Name;age=42;"
, using Data.Attoparsec.Text
:
import Control.Applicative ((<*), (*>))
import Data.Attoparsec.Text
import Data.Text (Text)
import GHC.Generics (Generic)
data Person = Person { name :: Text, age :: Int }
deriving (Show, Eq, Generic)
personParser :: Parser Person
personParser = Person
<$> (string "name=" *> takeTill (== ';') <* char ';')
<*> (string "age=" *> decimal <* char ';')
This parser defines a Person
and then, using applicative style, consumes "name="
, takes characters until a semicolon (discarding the semicolon), then consumes "age="
, parses a decimal (discarding its trailing semicolon), and populates the Person
fields.