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

Untyped Template Haskell quotes as patterns #529

Open
wants to merge 27 commits into
base: master
Choose a base branch
from

Conversation

Ericson2314
Copy link
Contributor

@Ericson2314 Ericson2314 commented Aug 5, 2022

The Template Haskell AST is inherently unstable. Let's make that less of an issue. We can do that by allowing Quotes to be used instead of Template Haskell AST data constructors in patterns.

Rendered

@david-christiansen
Copy link

A few questions about the interpretation of quotation patterns:

Would you allow any of the following, and would they recognize precisely the lambda expressions?

  1. isLambda [| \_ -> $(_) |] = True
  2. isLambda [| \$(_) -> $(_) |] = True

Is isLambdaLambda [| \$(_) -> $(_) -> $(_) |] = True equivalent to isLambdaLambda [| \$(_) $(_) -> $(_) |] = True?

Given that the language in the module that invokes the metaprogram that uses a quotation pattern may be using different GHC extensions than the module in which it occurs, what happens if there's e.g. BlockArguments enabled in just one of them? Are there any sets of incompatible syntactic extensions that would make it impossible to write a metaprogram that matched all possible user syntax?

@Ericson2314
Copy link
Contributor Author

Ericson2314 commented Aug 9, 2022

isLambda [| \$(_) -> $(_) |] = True

Returns True for any single parameter lambda. This is allowed.

isLambda [| \_ -> $(_) |] = True

Returns True for any lambda with a single _ parameter. Not the same!

Is isLambdaLambda [| \$(_) -> $(_) -> $(_) |] = True equivalent to isLambdaLambda [| \$(_) $(_) -> $(_) |] = True?

I assume you meant isLambdaLambda [| \$(_) -> \$(_) -> $(_) |] = True for the first one? (Note the second \ I added.)

Those would not be equivalent because the syntax being matched is different even though syntax has the same semantics.

(It would be interesting to do macros that respect various equational theories on syntax, but that is a huge leap from what we have today with Template Haskell. I think it is better to leave that out of scope.)


Instead, I rather create new splicing forms that allow one to e.g. splice (in positive and negative position) a list of parameters. e.g. suppose we could could do

isLambda [| \$(x) $..(_) -> $(_) |] = True

and that would match both

\(Pat foo) -> ignored
\(Pat foo) ignored -> ignored

in both cases binding [p| Pat foo |] as x.

My brief experience with @int-index exploring converting happy to TH (https://github.com/haskell/happy/tree/wip/template-haskell) indicated to me that were greatly lacking expressive power in the sorts of quotes and slices that are permitted --- the $..(thing) example being just one example.

Still, this too I think is best left as future work. We can nail down the core feature now, and then with a good foundation open the floodgates to much more quoting/splicing flexibility, I think that will work better.

@david-christiansen
Copy link

WRT the related work in Racket, the gold standard is no longer syntax-case and syntax-rules, but rather syntax-parse, which provides much better error messages along with re-usable sub-patterns. What you're proposing here is something even less powerful than syntax-case, as it won't preserve variable scopes, and I'm not sure we can reasonably implement something like syntax-parse on top of Haskell's pattern syntax. But it is good to know about it, and that we'll likely eventually want something similar.

The relevant paper is "Fortifying Macros" by Culpepper and Felleisen, and there's a Haskell implementation of its core as part of Crucible's concrete syntax.

@Ericson2314
Copy link
Contributor Author

Ericson2314 commented Aug 22, 2022

Updated to properly distinguish Scheme and Racket :), thanks @david-christiansen

@nomeata
Copy link
Contributor

nomeata commented Sep 7, 2022

@Ericson2314, are you by any chance attending Haskell Symposium? If so, would you like to present this proposal at the GHC Proposals session?

@Ericson2314
Copy link
Contributor Author

@nomeata I unfortunately am not going to ICFP --- and feeling some regret right now for sure!

@Ericson2314
Copy link
Contributor Author

Hmm I guess I forgot to submit this to the committee?

@nomeata
Copy link
Contributor

nomeata commented Nov 15, 2022

Looks like it :-). Is it ready fonr submission?

@Ericson2314
Copy link
Contributor Author

Ericson2314 commented Nov 15, 2022

@nomeata I think so! I mean to submit it.

@nomeata nomeata changed the title Template Haskell quotes as patterns Template Haskell quotes as patterns (under review) Nov 16, 2022
@nomeata nomeata added the Pending shepherd recommendation The shepherd needs to evaluate the proposal and make a recommendataion label Nov 16, 2022
@nomeata nomeata assigned gridaphobe and adamgundry and unassigned gridaphobe Nov 16, 2022
@int-index
Copy link
Contributor

int-index commented Dec 7, 2022

As far as terminology is concerned, I'd like to suggest to make a distinction between "pattern quotes" and "quote patterns".

Pattern quote: a Template Haskell quote that constructs a pattern, i.e. [p| ... |]
Quote pattern: a pattern that consists of a Template Haskell quote (i.e. the feature proposed here)

Based on this terminology, TemplateHaskellQuotesAsPatterns could be renamed to TemplateHaskellQuotePatterns.

@Ericson2314
Copy link
Contributor Author

I like that, @int-index. But moreover I would love to wash my hands of all name bike-shedding, purely following the consensus of others on this one :). So I hope you and @adamgundry can come to a decision on that!

@Ericson2314
Copy link
Contributor Author

@adamgundry I believe I have addressed most of the issues, except for the naming issue, and expanding the Related Work section.

Perhaps some sort of interactive discussion in what sort of topics would be useful to discuss, so I know what I should delve into.

Maybe a good starting point is also that the Scheme family macros work fundamentally differently, in that that the binding structure is unknown because the syntax is sexpression of unknown meaning until the final splice. Whereas we quote actual Haskell expressions and thus the quote-internal binding structure is known from the get-go, before manipulation. Perhaps therefore the most important one to investigate is Rust, since it is very Racket inspired but does allow quotes of expression etc. (rather than mere "token tree", it's s-expression equivalent) like us.

I am not at all familiar with what Idris and Lean do.

@adamgundry adamgundry added Pending shepherd recommendation The shepherd needs to evaluate the proposal and make a recommendataion and removed Needs revision The proposal needs changes in response to shepherd or committee review feedback labels Dec 12, 2022
@simonpj
Copy link
Contributor

simonpj commented Dec 12, 2022

I get the general motivation but lots of things are unclear here.

  1. Is this an extension to untyped Template Haskell, or to typed Template Haskell?
    I assume the former, but it would be much better to say so. The important point is that

    • Untyped TH splices can appear in patterns (and declarations and types) whereas typed TH splices are always expressions..
    • Untyped TH splices run during renaming, whereas typed TH spliced run during type checking.

    If it's untyped TH, then it doesn't make so much sense to talk about the typing rules for it.
    All we need to know is that any nested splices $p must be for patterns p.

  2. I'd love the relationship to quasi-quotes to be far more explicit. Quasi-quotations (-XQuasiQuotes) are
    essentially untyped Template Haskell. The quasi-quote [foo| string |] in an
    pattern context is precisely equvalent to $(quotePat foo "string"), where quotePat picks a field from the record foo :: QuasiQuoter.

    data QuasiQuoter = QuasiQuoter { quoteExp  :: String -> Q Exp,
                                     quotePat  :: String -> Q Pat,
                                     quoteType :: String -> Q Type,
                                     quoteDec  :: String -> Q [Dec] }
    

    This splice runs during renaming. For example:

    f [wombat| hello %x there |] = x+2
    

    here the quasiquote [wombat| hello %x there |] expands to a pattern that (presumably) binds x. But the syntax for this binding is entirely under the control of the wombat quasiquoter, which can do whatever it likes.

  3. Currently you can't use e, p, d, or t as the name of a quasiquoter.

    • In expression position [e| blah|] is an expression quote of type Q Exp, and [t| blah|] is a type quote of type Q Typ.
    • These forms are simply not allowed in pattern position, in types etc.

    So the proposal plans to make them meaningful in patterns. Well and good, but say so much more explicitly. It's really as if we are providing a rather special quasi-quoter e for which quotePat e does the thigns described here. Quite nice: fills out out a corner in the design.

  4. There is an awkwardness about binding. Consider

    f n = blah
    
    h x = [e| Just $(f 2) |]
    
    g [e| ($x,  $(f 2)) |] = ...
    

    In a normal expression splice, like in the RHS of h, the f is a bound occurrence of f, and the splice $(f 2) is run to compute the syntax tree to plug in instead of $(f 2).

    But what about in patterns? I think the $x is a binding occurrence; and I think
    that the splice $(f 2) is perhaps illegal, because it is understood as a pattern.
    (I think that is what the crypic statement "The second difference is that splices within these quotes contain patterns instead of expressions" means.)

    That means that splices in pattern-quotes can do no computation (unlike splices in expression-quotes). Maybe that's ok.

  5. "The third and final difference is that names in quotes must all be uses, never bindings." I have no idea what this means.

@Ericson2314 Ericson2314 changed the title Template Haskell quotes as patterns (under review) Untyped Template Haskell quotes as patterns (under review) Dec 12, 2022
@adamgundry
Copy link
Contributor

@simonpj

  1. "The third and final difference is that names in quotes must all be uses, never bindings." I have no idea what this means.

The examples point out that binding a name inside a quote-as-pattern is disallowed, so this is rejected because of the binding occurrence of x:

f [| \x -> x |] = ...

There is a bit more discussion of this in the Alternatives, section 6.2. The point is that picking the right semantics for such bindings seems nontrivial, so the proposal defers committing to a semantics.

Copy link
Contributor

@adamgundry adamgundry left a comment

Choose a reason for hiding this comment

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

Shepherd here. I've reviewed the updates and made a few more suggestions. Once @Ericson2314 has had a chance to look at these and @simonpj's comments, I'm inclined to recommend acceptance to the committee.

One other broad point: I'm a little worried that the implementation effort required for this proposal might be nontrivial. The Motivation section is clear when it comes to quotes of expressions, but could more clearly motivate support for quotes of other syntactic categories (notably declarations, where the restrictions on binding names seem to bite hard, and the fact that there may be more than one declaration needs thought). I can see that symmetry and consistency is one motivation, but are there motivating examples involving the other syntactic categories?

Comment on lines +124 to +129
Note we do have quotes *of patterns* today (``[p| ... |]``), but that is orthogonal.
This is quotes *as patterns*, the type of syntax being quoted doesn't matter and could be anything.
The point is the quotes are in negative position.

With this change put together, the hope is that a significant portion of TH out in the wild is going to be more stable across GHC versions.
This is all accomplished without trying to minimize TH AST changes, which is quite a hopeless task and also a perverse incentive for the rest of language development.
Copy link
Contributor

Choose a reason for hiding this comment

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

My point wasn't that quasiquotes make this proposal superfluous: rather, quasiquotes can already generate patterns (quotePat returns a Q Pat) so it makes sense to extend this to TH quoters. (This is Simon's point 3 in #529 (comment).)


- https://arxiv.org/pdf/2001.10490.pdf

Future Work
Copy link
Contributor

Choose a reason for hiding this comment

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

I thought about this some more, and realised that ideally we would want TExp to be a GADT, so that pattern-matching a TExp a with [|| \ $(x) -> $(y) ||] would refine a to be a function type. This seems hard. But it's fine to have this proposal be about Untyped TH and leave TTH for future work. 😁

Relax the rules so that TH Quotes only impose a ``Quote`` constraint when ``newName`` is in fact needed.
Otherwise, merely impose a ``Monad`` constraint.

[This was a `alaternative that was rejected <./0246-overloaded-bracket.rst#alternatives>` of Proposal #246, but now we have additional movation for it (as detailed in "Effectas and Interactions") below.]
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
[This was a `alaternative that was rejected <./0246-overloaded-bracket.rst#alternatives>` of Proposal #246, but now we have additional movation for it (as detailed in "Effectas and Interactions") below.]
[This was an `alternative that was rejected <./0246-overloaded-bracket.rst#alternatives>`_ of Proposal #246, but now we have additional motivation for it (as detailed in "Effects and Interactions") below.]

- ``[| ... |]`` or ``[e| ... |]``, where "..." is an expression, is a pattern that matches ``Exp``
- ``[p| ... |]``, where "..." is a pattern, is a pattern that matches ``Pat``
- ``[t| ... |]``, where "..." is a type, is a pattern that matches ``Type``
- ``[d| ... |]``, where "..." is a top-level declaration, is a pattern that matches a ``List Dec`` with a single item.
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm wondering about this restriction to a single item. Why is that needed? It seems a bit inconsistent with the fact that that quotes of declarations as expressions (and quasiquotes yielding declarations) may have multiple declarations.

For example, De Bruijn indices encode actions in a way that makes equality between the actions *themselves*, rather than their results, easily decidable.
This would be a less hacky solution.

Note that without this alternative, we still don't have to full back completely on not using our new feature for this use-case.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Note that without this alternative, we still don't have to full back completely on not using our new feature for this use-case.
Note that without this alternative, we still don't have to fall back completely on not using our new feature for this use-case.

Comment on lines +156 to +158
The third and final difference is that names in quotes must all be uses, never bindings.
The semantics of matching a name, either standalone, or inside a larger quote, is name equality.
This is formalized on the deguaring of a case alternative below::
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
The third and final difference is that names in quotes must all be uses, never bindings.
The semantics of matching a name, either standalone, or inside a larger quote, is name equality.
This is formalized on the deguaring of a case alternative below::
The third and final difference is that names in quotes must all be uses, never bindings.
The semantics of matching a name, either standalone, or inside a larger quote, is name equality.
This is formalized by the desugaring of a case alternative below::

Quotes as patterns
~~~~~~~~~~~~~~~~~~

With the new extension ``TemplateHaskellQuotesAsPatterns``, slightly modified quotes are usable in pattern position.
Copy link
Contributor

Choose a reason for hiding this comment

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

I see that @int-index also had a suggestion in #529 (comment), although my inclination is still to have explicit prepositions rather than relying on word order to distinguish "pattern quote" from "quote pattern". I'm happy to leave the bikeshed colour to be resolved later once the substance of the proposal is agreed, though.

I still think it would be helpful to have some explicit definitions, something like (with the current terminology):

  • A quote is said to be of the syntactic category being quoted, for example [e| ... |] is a quote of an expression and [p| ... |] is a quote of a pattern. Template Haskell already supports quotes of expressions, patterns, types and declarations, plus quotes of arbitrary syntax via quasiquotes.
  • A quote is said to be used as the syntactic category in which it occurs, for example x = [...| ... |] includes a quote as an expression whereas f [...| ... |] = ... includes a quote as a pattern. Template Haskell currently supports quotes as expressions and quasiquotes as all four categories; this proposal adds quotes as patterns.
  • Thus in f [t| Bool |] = [d| data T |] we have a quote of a type as a pattern and a quote of a declaration as an expression.

@nomeata
Copy link
Contributor

nomeata commented Jan 19, 2023

Should we mark this as “needs revision”?

@Ericson2314
Copy link
Contributor Author

Ericson2314 commented Jan 19, 2023

Yes please. And I had written it for HF consideration but it is now pretty far down in the future work on the draft proposal I am working on so it feels less urgent (perhaps I shouldn't have submitted it to the committee).

I am glad I wrote it, I am thankful @adamgundry reviewed it, but I feel less urgency pushing it to completion until the lower hanging fruit we can do re template-haskell compatibility (e.g. record fields as @bgamari pointed out) is plucked. I still think it is a good idea to do eventually, but as the saying goes "walk before you run".

@adamgundry
Copy link
Contributor

Thanks for this @Ericson2314, I'm happy to label this as "needs revision" for now and wait for you or another willing volunteer to decide to pick it up and get it over the line. As I indicated I think this is basically a solid idea, albeit a nontrivial one to implement and with a few interesting corners to discuss. 😄

@adamgundry adamgundry added Needs revision The proposal needs changes in response to shepherd or committee review feedback and removed Pending shepherd recommendation The shepherd needs to evaluate the proposal and make a recommendataion labels Jan 19, 2023
@sgraf812
Copy link
Contributor

sgraf812 commented Jun 13, 2023

As we discussed on Sunday (Ben's notes) and as the proposal states, writing such "quote patterns" is a great way for users that use TH for the macros/grammar use case (as opposed to the staging/code gen use case) to define their macros in a way that is far less susceptible to churn in the TH AST, plus it is far more ergonomically to use. Perhaps the discussion on Sunday would re-ignite @Ericson2314's interest on the matter?

As far as bike-shedding is concerned, I'd like to throw "Quotes in matches" or "matching quotes" into the ring. That expresses that these things must occur in a meta level pattern match, in "negative" position. There is no risk of confusing that with "Quote patterns" or "pattern quotes" where which is which I already forgot since I started this post. Unfortunately, a match is already a name describing the syntactic construct that encompasses a pattern and its GRHSs so that name isn't optimal either.

Perhaps we should take strong inspiration in https://docs.racket-lang.org/guide/pattern-macros.html (Edit: Or even the more closely related syntax-case: https://docs.racket-lang.org/guide/syntax-case.html). Example

foo :: Int -> Int
f [| foo (2*$(x)) |] = [| 2 * foo $(x) |]

(I hope I got that right.) Here, foo (2*$(x)) is called the pattern and 2 * foo $(x) is called the template. Both the pattern and the template are quoted ([| ... |]) and the quote has different semantics based on whether it's quoting a pattern or a template. A template quote that produces a pattern (with the [p|..] quoter) is separate from a pattern quote, which is a meta-level pattern taking the syntactic shape of a quote. As the proposal states, pattern quotes match on pure AST expressions whereas template quotes have monadic type.

Template Haskell used to have template quotes only, now it also got pattern quotes. (Makes you wonder if the name still flies.)

I don't think it makes sense to call f a pattern-based macro as defined by syntax-rules, because that term would apply to foo if f were automatically applied everywhere in the program; we currently lack such automated extension of the meta-level grammar (which in Racket you apparently do with define-syntax).

Rather, as @david-christiansen points out in #529 (comment), this proposal is quite similar to syntax-case (which is used to define syntax-rules).
David also points out that newer Rackets use a new thing called syntax-parse. Here are a few examples: https://school.racket-lang.org/2019/plan/tue-mor-lecture.html Indeed, syntax-parse seems pretty similar to typical uses of Template Haskell, too. I think the biggest difference is the notion of an actual syntax tree where and the ways in which you can tweak syntax-parse with directives, for example for better error info. I think we could have something similar by allowing type annotations to filter for specific kinds of matches, e.g.,

foo :: Int -> Int
f [| foo (2*$(x :: VarP)) |] = [| 2 * foo $(x) |]

Which certainly is a potential extension to this proposal.

Edit: Clarification on syntax-rules, syntax-case and syntax-parse. I still think I've got some of the definitions here wrong, though.


Quotes as Patterns
~~~~~~~~~~~~~~~~~~

Copy link
Contributor

Choose a reason for hiding this comment

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

Empty subsection. Intended?


because matching on lists of multiple declarations is left as future work.

Optional: Fine-grained Quotation constraints
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this can and should be a separate proposal. Perhaps move to Future Work instead?

Effect and Interactions
-----------------------

``TemplateHaskell`` will not imply ``TemplateHaskellQuotesAsPatterns``, though it does imply ``TemplateHaskellQuotes``.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think I'd prefer something like -XPatternQuotes after my reflection in #529 (comment). No need to include the then misnomer TemplateHaskell.

~~~~~~~~~~~~~~~~

The lack of symmetry where expression create actions but patterns only bind plain AST values is annoying.
But the fixes for this might be too radical?
Copy link
Contributor

Choose a reason for hiding this comment

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

I didn't understand what you meant here at first. IMO, give examples or move to Future Work!

Pattern match on actions(!)
~~~~~~~~~~~~~~~~~~~~~~~~~~~

I hypothesize that we could do better than the proposed actions vs no action asymmetry by meditating on the ways pattern matching relates to optics.
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this an alternative? Can't we have both? I'm not convinced that we want, though; seems confusing and almost no benefit (could just write the traverse form). Future Work?

Support local variables
~~~~~~~~~~~~~~~~~~~~~~~

Quotes that bind local variables do in fact have an interpretation as non-linear patterns::
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this section is confusing for these reasons:

  1. It discusses an extension to this proposal, namely binding constructs in patterns, that would be reasonable to implement in the future. So it belongs in Future Work.
  2. It calls these matches "non-linear", but of course the resulting desugaring is not non-linear in the meta language, as you readily point out.
  3. If this really were about non-linear matches, I'd totally expect __x1 == __x3 to hold.

Besides, I think the semantics you describe is very reasonable, because it allows for the expected round-tripping property: If I define

f [| (\x -> x, \x -> x) |] =...

... $(f [| (\x -> x, \x -> x) |] ...
... $(f [| (\z -> z, \z -> z) |] ...
... $(f [| (\a -> a, \b -> b) |] ...

Then I would expect all uses of f to match. Is that how it works in Racket and Lean, @david-christiansen @Kha?

Copy link

Choose a reason for hiding this comment

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

In macro systems like Racket's and Lean's, you cannot distinguish between bindings and uses in quotations because scoping is discovered only during expansion. So "quotes that bind local variables" is not even something we can detect in those systems.

Copy link
Contributor

Choose a reason for hiding this comment

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

I presume "discovered only during expansion" is an artifact of the fact that Racket-style macros will not get a name-resolved TH AST as input (where we know the binding structure but limit ourselves to macro syntax expressible in Haskell) but rather just a concrete syntax tree. Perhaps let me rephrase in terms of the example in https://school.racket-lang.org/2019/plan/tue-mor-lecture.html:

(define-syntax (robust-for/list5 stx)
  (syntax-parse stx
    [(_ ([elem-name:id seq]) computation)
     #'(map (λ (elem-name) computation) seq)]))

This macro will expand (robust-for/list5 ([x (list 1 2)]) (add1 x)) to (map (λ (x) (add1 x)) (list 1 2)), matching [elem-name :-> x, seq :-> (list 1 2)]. Note that elem-name is ultimately spliced into a binding occurrence and that computation may refer to the instantiation of elem-name, thus its syntax class is specified to be id, which is what elem-name:id does. (This is somewhat like pushing an expected type for the AST node to match inside the pattern, I guess, where "type" in Racket really means a user-definable non-terminal of the extensible syntax. See 5.6 in the link above.) But the pattern (_ ([elem-name:id seq]) computation) does not know about binding structure at all; rather the macro equips the pattern with a binding structure post-hoc when it generates the template (map (λ (elem-name) computation) seq)])) for the pattern, thus intentionally capturing occurrences of elem-name in computation.

Copy link

Choose a reason for hiding this comment

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

That's exactly right. It's the same reason I mentioned in the ZuriHac discussion why our macros are untyped (on the level of the quoted language) but core-level transformations can optionally be typed (which is done by https://github.com/gebner/quote4 btw).

f [|| $$(x) $$(y) ||] = ... :: delta

``x`` would be bound as ``x :: Code m (beta -> alpha)``, and
``y`` would be bound as ``y :: Code m beta``.
Copy link
Contributor

Choose a reason for hiding this comment

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

Tricky, and good thinking. Perhaps you need Monad m => or Applicative m => to have access to pure.
@mpickering probably knows what to do here; altough typed macros are probably not a priority to TTH (which focuses on staging).


None at this time.

Related Work
Copy link
Contributor

Choose a reason for hiding this comment

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

Correct me if I'm wrong, but since the proposal currently does not allow matching on binding constructs, we can't make hygiene better or worse. Judging from an hour worth reading, I also don't think we lock ourselves out with this proposal to more modern approaches such as syntax-parse because the stated semantics should be a subset of whatever advanced stuff we will happen to want in the future.

@adamgundry adamgundry removed their assignment Jan 22, 2024
@adamgundry adamgundry changed the title Untyped Template Haskell quotes as patterns (under review) Untyped Template Haskell quotes as patterns Jan 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs revision The proposal needs changes in response to shepherd or committee review feedback
Development

Successfully merging this pull request may close these issues.

None yet

10 participants