Zulip Chat Archive

Stream: lean4

Topic: Converting from doSeq to doSeqItem


Eric Wieser (Nov 15 2023 at 11:04):

Is there a better way to write the following?

def doSeqToItem {m: Type  Type} [Monad m] [MonadRef m] [MonadQuotation m]
    (t : TSyntax ``doSeq) : m (TSyntax ``doSeqItem) :=
  `(doSeqItem| if h : True then $t else (h trivial).elim)

Mario Carneiro (Nov 15 2023 at 11:09):

import Lean
open Lean Parser Term

def doSeqToItem {m: Type  Type} [Monad m] [MonadRef m] [MonadQuotation m]
    (t : TSyntax ``doSeq) : m (TSyntax ``doSeqItem) :=
  `(doSeqItem| do $t)

Mario Carneiro (Nov 15 2023 at 11:09):

you'd think this starts a new do scope, but it doesn't

Mario Carneiro (Nov 15 2023 at 11:12):

example :
  (Id.run do
    if true then
      do
        return 1
    else
      pure 0
    pure 10
  ) = 1 := rfl

example :
  (Id.run do
    if true then
      (do
        return 1)
    else
      pure 0
    pure 10
  ) = 10 := rfl

Eric Wieser (Nov 15 2023 at 11:20):

And a follow up question, how do I go from a TSyntax `doElem to a TSyntax `Lean.Parser.Term.doSeq : Type?

Eric Wieser (Nov 15 2023 at 11:24):

(and why is it a fake `doElem name and not a real declaration unlike doSeq?)

Mario Carneiro (Nov 15 2023 at 11:26):

doElem and a few others like term use unqualified names for the syntax kind, I think this is an outdated style and we would prefer they are all declarations but for now there are fake declarations like src#Lean.Parser.Category.term for hanging the docs for these

Mario Carneiro (Nov 15 2023 at 11:28):

what they have in common is these are all extensible syntax categories, not individual definitions

Mario Carneiro (Nov 15 2023 at 11:30):

def doElemToSeq {m: Type  Type} [Monad m] [MonadRef m] [MonadQuotation m]
    (t : TSyntax `doElem) : m (TSyntax ``doSeq) :=
  `(doSeq| $t:doElem)

Eric Wieser (Nov 15 2023 at 11:32):

It's not entirely clear to me what the difference between doSeqItem and doElem is

Mario Carneiro (Nov 15 2023 at 11:34):

not much:

def doSeqItem      := leading_parser
  ppLine >> doElemParser >> optional "; "

Eric Wieser (Nov 15 2023 at 12:02):

Thanks! The context here is https://github.com/leanprover-community/quote4/pull/27, where return is misbehaving

Mario Carneiro (Nov 15 2023 at 12:12):

oh that's right, quote4 had this horrible hack with comefrom being laundered through assert! to work around the fact that do elaboration is not extensible

Eric Wieser (Nov 15 2023 at 12:13):

To me it looks like comefrom is just an optimization

Eric Wieser (Nov 15 2023 at 12:13):

(in order to avoid duplicating a match alternative

Mario Carneiro (Nov 15 2023 at 12:13):

this line

  elabTerm ( `(have $n:ident : ?m := (do $b:doSeq); $body)) expectedType

is adding a new do scope

Mario Carneiro (Nov 15 2023 at 12:14):

possibly on purpose?

Mario Carneiro (Nov 15 2023 at 12:17):

no that's definitely the bug, although maybe it's not clear how to elaborate that in the context of the outer do block

Eric Wieser (Nov 15 2023 at 12:17):

I assume you saw that my PR deleted those lines already?

Mario Carneiro (Nov 15 2023 at 12:19):

can you explain what the new version is doing by example?

Eric Wieser (Nov 15 2023 at 12:20):

Its directly substituting the alternations as syntax, rather than trying to declare them as lets and resume them

Eric Wieser (Nov 15 2023 at 12:20):

I think the problem is that _qq_match is handling the alternation itsel

Mario Carneiro (Nov 15 2023 at 12:21):

does this involve duplicating syntax?

Eric Wieser (Nov 15 2023 at 12:21):

Yes, it does. Is that bad for other reasons?

Mario Carneiro (Nov 15 2023 at 12:23):

it involves duplicating it in a loop, no less

Eric Wieser (Nov 15 2023 at 12:23):

I think I understand a way to avoid doing that (build an Option of a sigma type, and ultimately do the final match on that), but it might be a larger refactor than I have time for today

Mario Carneiro (Nov 15 2023 at 12:23):

this seems like it would explode exponentially

Mario Carneiro (Nov 15 2023 at 12:24):

The usual technique used for the do elaborator is to capture the remainder of the block into a closure and jump to it under certain circumstances

Mario Carneiro (Nov 15 2023 at 12:24):

I think that's what the comefrom stuff was about

Eric Wieser (Nov 15 2023 at 12:24):

But that's not an option because it interferes with the real do notation

Eric Wieser (Nov 15 2023 at 12:25):

I think the solution here is that

let ~q(f $x $y) := e | alt

should be a macro for

let some x, y, match_eq := (do_q_match ~q(f $x $y) e) | alt

Mario Carneiro (Nov 15 2023 at 12:30):

what's the match_eq part about?

Mario Carneiro (Nov 15 2023 at 12:32):

Well, actually rather than doing two macro expansions I would just suggest building both the ⟨x, y⟩ pattern and the expression to go in for do_q_match ~q(f $x $y) e in a single go

Eric Wieser (Nov 15 2023 at 12:40):

Mario Carneiro said:

what's the match_eq part about?

It contains the $e =Q f $x $y term


Last updated: Dec 20 2023 at 11:08 UTC