1

I would like to define a DSL for writing lambda terms in Lean using macros a la the arithmetic example. I want to support syntax for multiple arguments in the lambda, and left-associativity. Thus far, I have come up with the following code:

inductive Λ where
 | var : String → Λ
 | apl : Λ → Λ → Λ
 | abstr : String → Λ → Λ
declare_syntax_cat lcplus
syntax ident : lcplus
syntax lcplus lcplus+ : lcplus
syntax "(λ" ident+ "." lcplus ")" : lcplus
syntax "(" lcplus ")" : lcplus
syntax "<[" term "]>" : lcplus
syntax "`[λ+| " lcplus "]" : term
macro_rules
 | `(`[λ+| $x:ident]) => `(Λ.var $(Lean.quote (toString x.getId)))
 | `(`[λ+| $x:lcplus $xs:lcplus*]) => do
 let mut acc <- `(`[λ+| $x])
 for x' in xs do
 acc <- `(Λ.apl $acc `[λ+| $x'])
 return acc
 | `(`[λ+| (λ $xs:ident* . $body:lcplus)]) => do
 let mut acc <- `(`[λ+| $body])
 for x in xs.reverse do
 acc <- `(Λ.abstr $(Lean.quote (toString x.getId)) $acc)
 return acc
 --xs.foldrM (init := `(`[λ+| $body])) λ x acc =>
 -- `(Λ.abstr $(Lean.quote (toString x.getId)) $acc) -- Type mismatch $acc, is Syntax, expected TSyntax `term
 | `(`[λ+| ($x:lcplus)]) => `(`[λ+| $x])
 | `(`[λ+| <[$e:term]>]) => pure e
 
#check `[λ+| (λ x y. x) a b ]

The issue is that `[λ+| (λ x y. x) a b ] parses as

Λ.apl (Λ.abstr "x" (Λ.abstr y (Λ.var "x"))) (Λ.apl (Λ.var "a") (Λ.var "b"))

while I would want it to parse as

Λ.apl (Λ.apl (Λ.abstr "x" (Λ.abstr y (Λ.var "x"))) (Λ.var "a")) (Λ.var "b")

i.e. it seems to be right-associative.

I suspect the issue lies in the syntax declaration

syntax lcplus lcplus+ : lcplus

and not in the macro itself, as I suspect that lcplus+ parses the rest of the lambda terms as another application rather than an array of lambda terms. I don't really know how to get around this, as my knowledge of Lean syntax and macros, and Lean in general, isn't great, and my knowledge of parsers is very rusty.

On another note, I could not figure out how to use a fold rather than do notation, as that is essentially what we are doing.

I would be grateful if someone could help me.

asked Apr 15, 2025 at 11:58

1 Answer 1

1

I figured it out.

First off, since the parser is already recursively using this rule:

syntax lcplus lcplus+ : lcplus

there is no point in the extra +. After closer inspection of the aforementioned arithmetic example, I figured out I should change this rule to the following:

syntax:60 lcplus:60 lcplus:61 : lcplus

to make it left-associative by specifying precedence.

I guess the question why the fold did not work still stands though.

answered Apr 15, 2025 at 18:45
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.