Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generalising many and some #141

Open
j-mie6 opened this issue Jan 4, 2023 · 2 comments
Open

Generalising many and some #141

j-mie6 opened this issue Jan 4, 2023 · 2 comments
Labels
enhancement New feature or request minor This change wouldn't affect existing parsers

Comments

@j-mie6
Copy link
Owner

j-mie6 commented Jan 4, 2023

Is your feature request related to a problem? Please describe.
As of parsley 4.0.0, many and some can be used to parse zero/one or more values into a List. This works pretty well, but occasionally, it is desirable to parse it into a different type, Vector or Array, say. In this sense, many and some are a bit wasteful.

Describe the solution you'd like
It might be nice to explore generalising these combinators to take in an implicit instance of a typeclass that helps build various collections, and use this internally. The low-priority implicits pattern could be used to ensure that List is chosen above other alternatives, say.

The cleanest way of doing this would be to support HKTs, so many[A, F[_]](p: Parsley[A])(...): Parsley[F[A]]), allowing for something like many[Char, Vector](p): Parsley[Vector[Char]], but this rules out three useful use cases: chars into strings, ints into strings, and (k, v) pairs into Maps. Annoyingly this means we'd be looking at many[A, C](p: Parsley[A])(...): Parsley[C], which places extra burden on implicit resolution to tie the knot, and more verbose type ascription when it goes wrong (i.e. many[A, Vector[A]]).

In any case, it's a bit annoying to have two parameters there, the A and the C/C[_]. Perhaps it's time to move many and some to be methods on Parsley itself? This would allow for p.many[Vector]/p.many[Vector[A]] which feels like an improvement. That said, perhaps it could be done via extension methods, and have two different kinds, one for HKTs and the other for everything more general?

Describe alternatives you've considered
Obviously, constructing stuff like Vector or Map, can be be using .foldRight or .foldLeft, but this doesn't leverage mutable builders. The use of mutable builders makes this pattern of use far more clumsy than it needs to be. The existence of stringOfMany and stringOfSome further points to this, and their implementations are non-trivial without the secret internal combinators within parsley: they are desirable though!

Additional Context
If we go down this route, we should be careful to explore the performance implications of "de-optimising" the existing many implementation.

@j-mie6 j-mie6 added enhancement New feature or request minor This change wouldn't affect existing parsers major This change would affect break backwards compatibility labels Jan 4, 2023
@j-mie6 j-mie6 added this to the Parsley 5 milestone Jan 4, 2023
@j-mie6
Copy link
Owner Author

j-mie6 commented May 29, 2023

Whatever we come up with here should ideally be applied to stuff like sepBy and sepEndBy etc (unless we go the method route for better inference...?)

@j-mie6
Copy link
Owner Author

j-mie6 commented Jan 11, 2024

Turns out, following the Scala 2.13+ way of using Factory, we can actually do this in minor. Most of the groundwork has been laid now, just need to expose an API

@j-mie6 j-mie6 removed the major This change would affect break backwards compatibility label Jan 11, 2024
@j-mie6 j-mie6 removed this from the Parsley 5 milestone Jan 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request minor This change wouldn't affect existing parsers
Projects
None yet
Development

No branches or pull requests

1 participant