Zulip Chat Archive
Stream: lean4
Topic: microcalc
Daniel Selsam (Feb 05 2021 at 01:45):
Missing features but super cool that you can write this in Lean itself:
open Lean
syntax calcStep := "..." "=" term:max ":" term
syntax "calc " term:max "=" term ":" term calcStep* : term
partial def expandCalc (rest : Array Syntax) (i : Nat) (stx : Syntax) : MacroM Syntax := do
if i == rest.size then stx else
let newStx ← `(Eq.trans $stx ($(rest[i][4]) : _ = $(rest[i][2])))
expandCalc rest (i+1) newStx
macro_rules
| `(calc $t1:term = $t2:term : $pf12:term $rest:calcStep*) => do
expandCalc rest 0 (← `(($pf12 : $t1 = $t2)))
Daniel Selsam (Feb 05 2021 at 01:45):
variable (t1 t2 t3 t4 : Nat)
variable (pf12 : t1 = t2) (pf23 : t2 = t3) (pf34 : t3 = t4)
theorem foo : t1 = t4 :=
calc t1 = t2 : pf12
... = t3 : pf23
... = t4 : pf34
Scott Morrison (Feb 05 2021 at 01:49):
Now the "relation-polymorphic" version, that allows using other transitive relations besides equality?
Mario Carneiro (Feb 05 2021 at 01:51):
that seems rather hard, since you would need to add a production for any infix operation. Is it possible to have a programmatic parser at the location of the "="
that does a lookup into the current set of notations to see what infix ops exist?
Daniel Selsam (Feb 05 2021 at 02:45):
Scott Morrison said:
Now the "relation-polymorphic" version, that allows using other transitive relations besides equality?
I am already exporting Mathlib relation manager attributes, so it wouldn't be hard to replicate the lean3 calc
mode. @Mario Carneiro the trick is to elaborate the expression up until the :
(which will resolve notation) and then just grab the operator name.
Mario Carneiro (Feb 05 2021 at 02:46):
That doesn't work for ... <= n
though, because that's not a valid expression (nor is <= n
)
Mario Carneiro (Feb 05 2021 at 02:46):
the syntax associated to the infix operator is something like term "<=" term
and that doesn't admit either form
Mario Carneiro (Feb 05 2021 at 02:48):
Perhaps it's possible to fake it by replacing ...
in the input with some placeholder that is a term like ()
and then parse () <= n
and postprocess the result
Daniel Selsam (Feb 05 2021 at 02:54):
I can replace ...
with the actual term, i.e. the rhs of the previous line
Mario Carneiro (Feb 05 2021 at 02:54):
sure, that works too
Daniel Selsam (Feb 05 2021 at 02:55):
Do people want the exact same calc
as before though? I was only implementing microcalc
for fun. I am happy to implement a durable calc
if people will use it.
Mario Carneiro (Feb 05 2021 at 02:55):
I'm not sure how you would go about replacing a term in the input stream though
Mario Carneiro (Feb 05 2021 at 02:55):
I'm sure people will want calc
, although it's probably not a high priority ATM
Kevin Buzzard (Feb 05 2021 at 06:07):
I was using calc with <= and < and = for teaching analysis in lean 3 yesterday, but I don't think I've ever used it in the mathlib code I've written
Johan Commelin (Feb 05 2021 at 06:09):
I use it regularly in mathlib code
Sebastien Gouezel (Feb 05 2021 at 07:53):
I use it a lot also. One point that was raised earlier is that it would make sense to have a syntax which resembles more closely other syntax, for instance replacing the weird :
with :=
.
Sebastian Ullrich (Feb 05 2021 at 10:47):
Here's one solution for a heterogeneous calc
based on a Trans
typeclass and ...
as a term notation:
class Trans (r : α → β → Prop) (s : β → γ → Prop) (t : outParam (α → γ → Prop)) where
trans {a b c} : r a b → s b c → t a c
export Trans (trans)
instance (r : α → γ → Prop) : Trans Eq r r where
trans heq h' := heq ▸ h'
instance (r : α → β → Prop) : Trans r Eq r where
trans h' heq := heq ▸ h'
notation "..." => _
-- enforce indentation of calc steps so we know when to stop parsing them
syntax calcStep := colGe term " := " term
syntax "calc " withPosition(calcStep+) : term
macro_rules
| `(calc $p:term := $h:term) => `(($h : $p))
| `(calc $p:term := $h:term $rest:calcStep*) => `(trans _ _ _ ($h : $p) (calc $rest:calcStep*))
variable (t1 t2 t3 t4 : Nat)
variable (pf12 : t1 = t2) (pf23 : t2 = t3) (pf34 : t3 = t4)
theorem foo : t1 = t4 :=
calc
t1 = t2 := pf12
... = t3 := pf23
... = t4 := pf34
variable (t5 : Nat)
variable (pf23' : t2 < t3) (pf45' : t4 < t5)
instance [HasLess α] : Trans (α := α) Less Less Less where
trans := sorry
theorem foo' : t1 < t5 :=
calc
t1 = t2 := pf12
... < t3 := pf23'
... = t4 := pf34
... < t5 := pf45'
Sebastian Ullrich (Feb 05 2021 at 10:50):
In fact ...
is now barely carrying its weight and one should probably just use _
directly
Kevin Buzzard (Feb 05 2021 at 10:53):
I am really not engaged with Lean 4 at all, because as a mathematician with essentially no programming background but ambitions to do serious mathematics in Lean, all I know is that Lean 4 is basically useless to me until I can have mathlib. However I am extremely impressed with the way that people are doing things like this -- "oh by the way there's no calc
right now, but of course if you want one then you can just knock one up in a few lines of code". I've never written a line of meta code in my life and I suspect I won't be writing too many macros either, but I can really see that we have something exciting to look forward to.
Last updated: Dec 20 2023 at 11:08 UTC