Types of parser combinators

If I have a : Parser A parser and b : Parser B parser, then I can combine it into a | b : Parser (Either AB) parser a | b : Parser (Either AB) . This works, but it gets a little complicated when you start adding more alternatives and getting types like Either A (Either BC) . I can imagine equating the previous type to something like Alternative ABC . Is there a standard conversion that I can perform, or am I stuck with creating a whole set of templates for types like Alternative ABC ...

+5
source share
2 answers

So, the interesting thing about Either is that you can use it as a cons level operator at the level level.

 A `Either` (B `Either` (C `Either` (D `Either` Void))) --> [A,B,C,D] 

So all we need to do is make it explicit. You will need ghc-7.8 to support private data families:

 {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE DataKinds #-} -- ... type family OneOf (as :: [*]) :: * where OneOf '[a] = a OneOf (a ': as) = Either a (OneOf as) 

Now you can write your types much more succinctly:

 aorborc :: Parser (OneOf '[A, B, C]) aorborc = a | (b | c) 

It is still Either under the hood, so you can still easily interact with all existing code that uses Either , which is nice.

+8
source

There is only one possible type of sum in Haskell, and because of the finished class instances and helper functions, it is useful in many cases, but it becomes significantly clunkier when you insert it.

The best approach for the analyzer is to create your own data type, which reflects the structure that you analyze and analyze it directly. Let me give you an example of a partial toy about a toy language.

 data Statement = TypeDec String Type DataDec String [Constructor] FunctionDec String LambdaExpression statement :: Parser Statement statement = TypeDec <$> string "type " *> identifier <*> string " = " *> type <|> DataDec <$> string "data " *> identifier <*> string " = " *> many constructor <|> FunctionDec <$> identifier <*> string " = " *> lambdaExpression 

Thus, both your data structure and your code reflect production processes in the grammar that you analyze. The great benefit of this is that your data is safe, understandable and ready to use as soon as it is analyzed.

(I never remember the corrections *> and <* , so I probably did it the way you need brackets or something like that, but hopefully you get this idea.)

+3
source

Source: https://habr.com/ru/post/1200786/


All Articles