Zulip Chat Archive

Stream: general

Topic: Problems with notation overloading


Tomas Skrivan (Oct 01 2020 at 22:17):

I'm having problems with overloading a notation.

Everything works fine without overloading

notation x | y := pair[x][y]
variables {X Y Z : type} {x : X} {y : Y} {z : Z}
#check (x|y)
| pair[x][y] : Expr (X × Y)

However, adding an overload for the notation produces:

notation x | y := pair[x][y]
notation x | y := pair[x][y]
variables {X Y Z : type} {x : X} {y : Y} {z : Z}
#check (x|y)
| (λ (x_1 : Expr X), pair[x_1].app) x y : Expr (X × Y)

Why do I get (λ (x_1 : Expr X), pair[x_1].app) x y : Expr (X × Y) instead of pair[x][y] ?

This actually causes a failure of overload resolution for (x|y)|x with an error:

error for λ (x_1 : _), [choice Expr.app' Expr.app] ([choice Expr.app' Expr.app] (quotient.mk pair) x_1)
type mismatch at application
  (λ (x_1 : quotient ?m_1.setoid), Expr.app' pair[x_1]) ((λ (x_1 : Expr X), pair[x_1].app) x y)
term
  (λ (x_1 : Expr X), pair[x_1].app) x y
has type
  Expr (X × Y)
but is expected to have type
  quotient ?m_1.setoid

error for λ (x_1 : _), [choice Expr.app' Expr.app] ([choice Expr.app' Expr.app] pair x_1)
type mismatch at application
  (λ (x_1 : Expr (X × Y)), pair[x_1].app) ((λ (x_1 : Expr X), pair[x_1].app) x y) x
term
  x
has type
  X
but is expected to have type
  Expr ?m_1[(λ (x_1 : Expr X), pair[x_1].app) x y]

Reid Barton (Oct 01 2020 at 22:32):

I wouldn't recommend overloading notation, except possibly in cases where it's really obvious to Lean which variant is needed.

Tomas Skrivan (Oct 01 2020 at 22:41):

Not sure what is 'really obvious' but in my case those overloads either act on a type or on its quotient.

Reid Barton (Oct 01 2020 at 22:43):

Well, for example, since I don't know what pair[x] means, I couldn't tell which variant is expected in your #check example, except from context

Reid Barton (Oct 01 2020 at 22:46):

We don't really use overloaded notation, instead we use type classes. If you want to "overload function application" then you can create an instance of has_coe_to_fun.

Tomas Skrivan (Oct 01 2020 at 22:53):

I will have look at has_coe_to_fun.

Anyway, #check pair[x] gives pair[x] : Expr (?M_1 ⟶ X × ?M_1), it pairs with x.

Reid Barton (Oct 01 2020 at 22:55):

Is this [ ] notation also overloaded?

Tomas Skrivan (Oct 01 2020 at 22:57):

Yes it is. I'm working with a type representing expressions

inductive Expr : type  Type
| sym (T : type) (name : string) : Expr T
| app {X Y : type} : Expr (X  Y)  Expr X  Expr Y

notation f [ x ] := Expr.app f x

Tomas Skrivan (Oct 01 2020 at 22:59):

And it is also defined on the quotient

def Expr.app' {X Y : type} := quotient.lift₂ (λ f  x, f[x])
notation f [ x ] := Expr.app' f x

Reid Barton (Oct 01 2020 at 23:16):

Yeah, so in this situation I would not trust Lean to pick the correct overload variants.

Eric Wieser (Oct 01 2020 at 23:18):

So lean actually does support overloading without the usual approach of typeclasses? Is this documented anywhere?

Reid Barton (Oct 01 2020 at 23:32):

I'm pretty sure Lean makes some nonzero effort to select the right notation based on the available type information--it definitely does this for disambiguating the same name in several different open namespaces, which is a feature used mainly without being aware of it.

Eric Wieser (Oct 01 2020 at 23:37):

So functions can be overloaded by declaring them in different namespaces then opening both?

Reid Barton (Oct 01 2020 at 23:41):

Yes, or more commonly when a function in an opened namespace has the same name as one in the root namespace

Sebastian Ullrich (Oct 02 2020 at 08:32):

Overloaded names and notations are simply tried in turn, after which the unique successful interpretation is taken if any


Last updated: Dec 20 2023 at 11:08 UTC