If I have a parser a : Parser A
and a parser b : Parser B
then I can combine it into a parser a | b : Parser (Either A B)
. This works but gets a little tricky when you start adding more alternatives and getting types like Either A (Either B C)
. I can imagine flattening the previous type into something like Alternative A B C
. Is there a standard transformation I can perform or am I stuck with generating a whole bunch of boilerplate for types like Alternative A B C ...
.
相关问题
- Correctly parse PDF paragraphs with Python
- R: eval(parse()) error message: cannot ope
- Extracting from a Union Type when some have identi
- Understanding do notation for simple Reader monad:
- How do I parse a .pls file using PHP? Having troub
相关文章
- Is it possible to write pattern-matched functions
- Haskell underscore vs. explicit variable
- Top-level expression evaluation at compile time
- How do I get from a type to the TryParse method?
- Stuck in the State Monad
- foldr vs foldr1 usage in Haskell
- Java Generics: How to specify a Class type for a g
- List of checkboxes with digestive-functors
So the interesting thing about
Either
is that you can use it as a type-levelcons
operator.So all we need do is make that explicit. You'll need ghc-7.8 to support closed data families:
Now you can write your types much more succinctly:
It's still
Either
under the hood, so you can still easily interoperate with all existing code that usesEither
, which is nice.Either is just one possible sum type in Haskell, and because of the ready made class instances and helper functions is useful for many cases, but becomes considerably clunkier when you nest it.
The best approach for a parser is to create your own data type that mirrors the structure you're parsing and parse directly into that. Let's make a partial toy example about a toy language.
In this way, both your data structure and your code mirror the productions in the grammar you're parsing. The great benefit to that is that your data is type safe, clear and ready to use as soon as it's parsed.
(I can never remember the fixities of
*>
and<*
, so I've probably done it the way you need brackets or something, but hopefully you get the idea.)