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

Add printer combinators dual to parser combinators #71

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

echatav
Copy link

@echatav echatav commented Feb 28, 2022

Divisible Combinators

  • (>*)
  • (*<)

Decidable Combinators

  • optionalD
  • manyD
  • many1D
  • sepByD
  • sepBy1D

# `Divisible` Combinators

  * `(>*)`
  * `(*<)`

# `Decidable` Combinators

  * `optionalD`
  * `manyD`
  * `many1D`
  * `sepByD`
  * `sepBy1D`
`(>*<)`, `(>*)`, and `(*<)` are `Divisible` operators, not requiring a `Decidable` constraint
Copy link

@endgame endgame left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, is it worth adding (>|), (|<), and (>|<) from the gwils talk?

manyD p = choose (mayhaps . uncons) conquered (many1D p)

-- | One or more.
many1D :: Decidable f => f a -> f (a,[a])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possibly more ergonomic to work with a NonEmpty a than an (a, [a])?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe, but I don't really think NonEmpty is much better (and it has an evil IsList instance) than the pair and this matches better with divide. I could be convinced otherwise.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know either; just wanted to flag it.

Copy link
Author

@echatav echatav Feb 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we used NonEmpty a in many1D then you'd have to pay the cost of conjugating by the isomorphism NonEmpty a <-> (a,[a]) in manyD (at least if we do the naive thing).

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do like NonEmpty here, even if there is a little bit of overhead.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I added a commit to use NonEmpty. I think the cost is n-1 calls conjugating by the isomorphism for a list of length n. Happy to make any other changes to fixity or naming.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or I could just write a helper function and not be naive. Ok, now the cost is just 1 call conjugating by the isomorphism.

(*<) :: Divisible f => f a -> f () -> f a
p *< after = (,()) >$< p >*< after

infixr 5 *<
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The @gwils talk uses infixr 4. Not saying that one is correct, but is there a reason?

https://youtu.be/IJ_bVVsQhvc?t=1311

Copy link
Author

@echatav echatav Feb 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't seen this talk yet. My reasoning was by analogy. The Applicative operators are all infixl 4.

infixl 4 <*>
infixl 4 <*
infixl 4 *>

The Divisible operator so far is infixr 5 >*< so I gave >* and *< the same fixity. I'm not sure that's "correct".

Copy link
Author

@echatav echatav Feb 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like I switched the signatures of *< and >* from that talk too, oops.

simplify definitions for `(>*)` and `(*<)`
@echatav
Copy link
Author

echatav commented Feb 28, 2022

Also, is it worth adding (>|), (|<), and (>|<) from the gwils talk?

I think (>|<) should be added in another PR since it's just a synonym for chosen. I don't think the others exist.

@echatav
Copy link
Author

echatav commented Mar 1, 2022

Also, is it worth adding (>|), (|<), and (>|<) from the gwils talk?

I think (>|<) should be added in another PR since it's just a synonym for chosen. I don't think the others exist.

I also think that Tom Ellis's(><) = divide (\a -> (a, a)) should be added in another PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants