Zulip Chat Archive

Stream: mathlib4

Topic: Preferring homogeneous operators


Siddhartha Gadgil (Apr 08 2023 at 07:19):

Here is my attempt to address the issue https://github.com/leanprover/lean4/issues/1915 raised by @Kevin Buzzard (also commented on by @Mario Carneiro). I am posting for feedback, specifically on

  • Whether the expressions generated will be compatible with those usually found in mathlib4 (so this can be imported for improved syntax).
  • Whether this is likely to work in general.
  • How it can be improved.

The basic approach is to write (scoped) elaborators with higher priority that, if the desired type is known, infer arguments using this. Here is the code:

import Lean
import Mathlib
open Lean Meta Elab Term

namespace Homogeneous

attribute [-instance] Nat.instDivNat
example (n : ) :  := ((4 *((n*(n-1)/2 : )^3 : ) - (((n*(n-1)/2 : )^2) : )) : )/3

scoped syntax  (name := homdiv) (priority := high) term:71 " / " term:70 : term
scoped syntax  (name := hommul) (priority := high) term:71 " * " term:70 : term
scoped syntax  (name := homadd) (priority := high) term:66 " + " term:65 : term
scoped syntax  (name := homsub) (priority := high) term:66 " - " term:65 : term

scoped syntax  (name := hompow) (priority := high) term:85 "^" term:86 : term

@[term_elab homdiv] def elabDiv : TermElab := fun stx expectedType? => do
  -- logInfo m!"elabDiv {stx} {expectedType?}"
  match stx with
  | `($x / $y) => do
    match expectedType? with
    | none =>
        let x  elabTerm x none
        let y  elabTerm y none
        mkAppM ``HDiv.hDiv #[x, y]
    | some expectedType =>
        let x  elabTermEnsuringType x (some expectedType)
        let y  elabTermEnsuringType y (some expectedType)
        mkAppOptM ``HDiv.hDiv #[some expectedType, some expectedType, some expectedType, none, x, y]
  | _ => throwUnsupportedSyntax

@[term_elab hommul] def elabMul : TermElab := fun stx expectedType? => do
  -- logInfo m!"elabMul {stx} {expectedType?}"
  match stx with
  | `($x * $y) => do
    match expectedType? with
    | none =>
        let x  elabTerm x none
        let y  elabTerm y none
        mkAppM ``HMul.hMul #[x, y]
    | some expectedType =>
        let x  elabTermEnsuringType x (some expectedType)
        let y  elabTermEnsuringType y (some expectedType)
        mkAppOptM ``HMul.hMul #[some expectedType, some expectedType, some expectedType, none, x, y]
  | _ => throwUnsupportedSyntax

#check @HAdd.hAdd

@[term_elab homadd] def elabAdd : TermElab := fun stx expectedType? => do
  -- logInfo m!"elabAdd {stx} {expectedType?}"
  match stx with
  | `($x + $y) => do
    match expectedType? with
    | none =>
        let x  elabTerm x none
        let y  elabTerm y none
        mkAppM ``HAdd.hAdd #[x, y]
    | some expectedType =>
        let x  elabTermEnsuringType x (some expectedType)
        let y  elabTermEnsuringType y (some expectedType)
        mkAppOptM ``HAdd.hAdd
          #[some expectedType, some expectedType, some expectedType, none, x, y]
  | _ => throwUnsupportedSyntax


@[term_elab homsub] def elabSub : TermElab := fun stx expectedType? => do
  -- logInfo m!"elabSub {stx} {expectedType?}"
  match stx with
  | `($x - $y) => do
    match expectedType? with
    | none =>
        let x  elabTerm x none
        let y  elabTerm y none
        mkAppM ``HSub.hSub #[x, y]
    | some expectedType =>
        let x  elabTermEnsuringType x (some expectedType)
        let y  elabTermEnsuringType y (some expectedType)
        mkAppOptM ``HSub.hSub #[some expectedType, some expectedType, some expectedType, none, x, y]
  | _ => throwUnsupportedSyntax

@[term_elab hompow] def elabPow : TermElab := fun stx expectedType? => do
  -- logInfo m!"elabPow {stx} as {expectedType?}"
  match stx with
  | `($x ^ $y) => do
    -- logInfo m!"elabPow {x} to the power {y}"
    match expectedType? with
    | none =>
        let x  elabTerm x none
        let y  elabTerm y none
        mkAppM ``HPow.hPow #[x, y]
    | some expectedType =>
        let x  elabTermEnsuringType x (some expectedType)
        try
          let y  elabTerm y (mkConst ``Nat)
          mkAppOptM ``HPow.hPow #[some expectedType, some (mkConst ``Nat), some expectedType, none, x, y]
        catch _ =>
          let y  elabTerm y none
          mkAppOptM ``HPow.hPow #[some expectedType, none, some expectedType, none, x, y]
  | _ => throwUnsupportedSyntax

end Homogeneous

open Homogeneous

def eg1 (n : ) :  :=  (4*(n*(n-1)/2)^3-(n*(n-1)/2)^2)/3

set_option pp.all true in
#print eg1

Last updated: Dec 20 2023 at 11:08 UTC