Hacker News new | ask | show | jobs
by tel 4483 days ago
For the extra curious, here's a little Parser (untested, poor design, but generally the right idea)

    newtype Parser a = Parser { unParser :: MaybeT (State String) a }
      deriving ( Functor, Applicative, Alternative, 
                 Monad, MonadPlus, MonadTrans, 
                 MonadState String )
        -- why write boilerplate when the 
        -- compiler will for you?

    runParser :: Parser a -> String -> Maybe a
    runParser input = flip evalStateT input . runMaybeT 

    -- | Parses a single character if it passes a predicate
    satisfy :: (Char -> Bool) -> Parser Char
    satisfy p = do
      (c:cs) <- get
      guard (p c)
      put cs
      return c
 
    char :: Char -> Parser Char
    char c = satisfy (== c)

    -- | Parses a whole string
    string :: String -> Parser String
    string = mapM char

    -- | Converts a parser to be surrounded by parentheses
    parens :: Parser a -> Parser a
    parens p = char '(' *> p <* char ')'