codehakase.com

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.