
I'm writing a parser for polynomial equation (ex : 5 x ^2 + 3 x ^ 1 = 3 x ^ 2). I'm using parsec to decompose my parser into smaller parts, and it works, but all my parser functions have the type : parser :: Stream s m Char => ParsecT s u m <Type to Parse> Is there a way to factor out that boilerplate, in such a way that I could simply write a type like parser :: Parser <Type to parse> ? The farther I've been is : type Parser s = ParsecT s () Identity type St = Stream s Identity Char (using ConstraintKinds) parser :: St s => Parser s <Type to Parse> But that still feels tedious to write every time... I've tried to search the wiki and the internet in general, but did not find an answer to that particularly. Thxs a lot if you have any hindsights. Max Gautier

Hello Max, On Tue, Mar 24, 2020 at 04:06:03PM +0100, Max Gautier wrote:
Is there a way to factor out that boilerplate, in such a way that I could simply write a type like parser :: Parser <Type to parse> ?
The farther I've been is : type Parser s = ParsecT s () Identity type St = Stream s Identity Char (using ConstraintKinds) parser :: St s => Parser s <Type to Parse>
But that still feels tedious to write every time...
Is there any reason you are using `St s => s ...` rather than a concrete type? If not, type MyPar a = ParsecT Char () Identity a p :: MyPar Int could be useful. Does that work for you? -F

Hi Francesco. If I understand correctly the parsec interface, leaving the stream type s as a type variable allows me to specify the concrete stream type at the time of use without changing the parser, as long as that stream gives Char tokens, is that correct ? And using a concrete stream type forfeit that, does'nt it ? (So for example in Quickcheck tests in can just use a String as my stream, and in other contexts something like Text). (I have not really experimented yet with the various "string" type, so maybe this is unnecessary (but in that case, what is the point of ParsecT exposing these type parameters ?)) The main purpose of my project is to learn Haskell, so I'm trying to understand the full power of the tools I use^ .

Before replying, my example should have of course been: type MyPar a = ParsecT String () Identity a On Tue, Mar 24, 2020 at 06:08:42PM +0100, Max Gautier wrote:
If I understand correctly the parsec interface, leaving the stream type s as a type variable allows me to specify the concrete stream type at the time of use without changing the parser, as long as that stream gives Char tokens, is that correct ? And using a concrete stream type forfeit that, does'nt it ?
Yes you do forfeit polymorphism using a concrete type. With your current synonym: type Parser s = ParsecT s () Identity you already missing polymorphism on state (`()`) and a monadic transformers (`Identity`). Parsec itself [1] uses a very similar shorthand type Parser = Parsec String () [1] https://hackage.haskell.org/package/parsec-3.1.14.0/docs/Text-Parsec-String.... I do not think there is a sensible way not to have the constraint part (`... =>`) written out in full.
participants (2)
-
Francesco Ariis
-
Max Gautier