content: {-# LANGUAGE FlexibleInstances, TypeApplications, RankNTypes, CPP #-}
  import Data.List
  import Data.Traversable
  import Data.Maybe
  import Data.Void
  import Control.Monad
  
  import Criterion.Main
  
  import Text.Regex.Applicative
  import qualified Text.Parser.Combinators as PC
  import qualified Text.Parser.Char as PC
  import Control.DeepSeq
  import qualified Text.Parsec as Parsec
  import qualified Text.Megaparsec as Megaparsec
  import qualified Text.Megaparsec.Parsers as MP
  import qualified Data.Attoparsec.ByteString.Char8 as Attoparsec
  import qualified Data.ByteString.Char8 as BS8
  
  parser1 :: PC.CharParsing f => f [String]
  parser1 = many $
    PC.try (PC.string "foo") <|>
    PC.try (PC.string "bar") <|>
    PC.string "baz"
  
  str :: String
  str = concat $ replicate 10 "foobarfoobarbaz"
  
  benchmarkParser
    :: NFData a
    => (forall f . (PC.CharParsing f) => f a)
    -> [Benchmark]
  benchmarkParser parser =
      [ bench "regex-applicative" $ nf (match parser) str
      , bench "parsec" $ nf (Parsec.parse parser "-") str
      , bench "megaparsec" $ nf (Megaparsec.parseMaybe @Void (MP.unParsecT parser)) str
      , bench "attoparsec" $ nf (Attoparsec.parseOnly parser) (BS8.pack str)
      ]
  
  main = defaultMain $
    [ bgroup "parsing" (benchmarkParser parser1)
    , bgroup "recognizing" (benchmarkParser (void parser1))
    ]
  
  -- instances
  instance PC.Parsing (RE c) where
    try = id
    (<?>) = const
    unexpected _ = empty
    notFollowedBy = error "RE: notFollowedBy"
    eof = error "RE: eof"
  instance PC.CharParsing (RE Char) where
    satisfy = psym
    char = sym
    anyChar = anySym
    string = string
  instance NFData Parsec.ParseError where
    rnf = flip seq ()
  