-
Notifications
You must be signed in to change notification settings - Fork 24
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
base: main
Are you sure you want to change the base?
Conversation
# `Divisible` Combinators * `(>*)` * `(*<)` # `Decidable` Combinators * `optionalD` * `manyD` * `many1D` * `sepByD` * `sepBy1D`
`(>*<)`, `(>*)`, and `(*<)` are `Divisible` operators, not requiring a `Decidable` constraint
There was a problem hiding this 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]) |
There was a problem hiding this comment.
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])
?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 *< |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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".
There was a problem hiding this comment.
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 `(*<)`
I think |
I also think that Tom Ellis's |
Divisible
Combinators(>*)
(*<)
Decidable
CombinatorsoptionalD
manyD
many1D
sepByD
sepBy1D