3 ms·
Slightly off-topic; a tiny bit of Parsec advice—you don't actually need the undercore at all. queryExpression can be equivalently expressed as queryExpress
by andolanra 16y ago
Slightly off-topic; a tiny bit of Parsec advice—you don't actually need the undercore at all. queryExpression can be equivalently expressed as
queryExpression = do
char '{'
sqlValue <- sqlLanguageSelectStatement
char '}'
return $ QueryExpression sqlValue
and it will be exactly the same parser.
Incidentally, my personal preference is not to use do-notation at all and instead to use applicative functors (as they do in Real World Haskell, c.f. http://book.realworldhaskell.org/read/using-parsec.html#id652399 http://book.realworldhaskell.org/read/using-parsec.html#id65... ) I think it makes code more concise and readable. In that case, queryExpression would look like
queryExpression = QueryExpression <$> (char '{' *> sqlLanguageSelectStatement <* char '}')
which again does exactly the same thing. (The * > operator chains things together but throws away its left-hand side, and <* does the same but throws away its right-hand side, so you're left with the result from parsing sqlLanguageSelectStatement, and <$>, which is a synonym for fmap, reaches in and wraps the result of the parser in a QueryExpression. The only downside is you have to write the Applicative instance yourself, but because GenParser is already a monad, all you need to do is define each method to be the equivalent monad method, which they show in the link above.)
As for your broad idea—the only issue is that sometimes parser combinators aren't as fast or finely tuned as a handwritten parser, and there's a chance that you'd have to do some kind of backtracking. But the short answer is yes, that is exactly what parser combinators are designed to do, and they do it pretty well and very easily.
- jerf 16y agoI got the _ from HLint, which suggested it in general when discarding values in do notation. Mostly I ignored it but in parsers in particular I found it helpful. Your applicative functor approach eliminates the need for it anyhow, which is also a, uh, what's the opposite of a code smell? Code disinfectant? I'll adopt that, thanks.