Hacker News new | ask | show | jobs
by tel 4483 days ago
(And is a really great example motivating both monads and monad transformers, for the curious!)
2 comments

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 ')'
The shallow DSL in the LLVM monad is really nice, it looks almost like the IR itself but you can abstract over it and compose it with other code. DSLs are often overlooked when talking about monad use cases.
I really need to explore LLVM in more detail at some point.