Hi Li-yao,

I appreciate your help especially the PR as a working fix. 

But personally I don't like the overall method of your solution, I can see Monad Transformers are powerful enough to tackle similar problems, but I'm not satisfied by the ergonomics in composing monads with transformers. `ParsecT` had already caused me much pain to get started in the beginning, and I'm still not fluent (comfortable) in transforming monads, especially I'm afraid I will have to transform much of the standard combinator functions, in order to get the real case parser working, as its resulting AST is much more complex.

I still have faith in the improvement of megaparsec as a well known parser combinator library (I regard it as the best for engineering needs among other libraries), and I must admit megaparsec already elegantly works 99% out of my current use cases, and the very issue we are talking about  is a nice-to-have rather than must-to-have, so I would think we still have time to anticipate more options to come out. 

And I particularly like to see parser combinators have this issue addressed in its own design space.

Thanks again with best regards,
Compl


On Wed, Oct 28, 2020 at 8:19 PM Li-yao Xia <lysxia@gmail.com> wrote:
Hi Compl,

At least, for the example you gave on this list, it can be fixed by
returning Nothing instead of using the facility for failure baked into
(mega)parsec. (Proposed diff for reference:
https://github.com/complyue/dcp/pull/3)

"Returning Nothing" can be seen as adding a new channel for errors,
turning the Parser monad into `MaybeT Parser`. Then `return Nothing` is
how `empty` is defined by `MaybeT`, allowing that error to be caught and
recovered from at the point where it was thrown, no backtracking. (And
the original failure mode of Parser becomes `lift empty`.)

Does that address your problem?

Cheers,
Li-yao

On 10/28/2020 5:18 AM, Compl Yue wrote:
> (sorry for repost, seems GMail's html processing on my last email has
> rendered it barely readable, so again with plain text here)
>
> Dear Cafe,
>
> I'm still not fully clear about the confusion regarding megaparsec's
> behavior that I posted lately here. But now comes to my mind that it may
> have some problem rooted in the lacking of recoverability semantic with
> respect to parser combinators, some quoting from
> http://hackage.haskell.org/package/parser-combinators/docs/Control-Applicative-Combinators.html
>
> The  *A note on backtracking* section
>
>  > Combinators in this module are defined in terms Applicative and
> Alternative operations.
>
> And `empty`'s doc:
>
>  > This parser fails unconditionally without providing any information
> about the cause of the failure.
>
> Clearly `empty` is used to express failure, but there is seemingly no
> device to explicitly express whether a failure is recoverable. Then I
> observed megaparsec's implicit rule as currently implemented is like:
>
> *) a failure with no input consumed can be recovered by rest parsers
> *) a failure with some input consumed can not be recovered by rest parsers
>
> This works to great extent, but I would think the expressiveness can be
> further extended for a parser from the application, to tell the library
> that some input induces recoverable failure.
>
> I have no expertise to suggest whether `MonadPlus` and/or `MonadFail`
> are suitable devices to be considered, but as megaparsec has implemented
> instances for them, I do feel some tweaks would be possible and meaningful.
>
> Best regards,
> Compl
>
>
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.
>