Zulip Chat Archive

Stream: new members

Topic: defining something outside a class or inside


Michael Beeson (Feb 16 2021 at 02:04):

I have a class Model with an operation 'multiplication' that I write infix as x*y. But I would like to
define it using some stuff that has been defined after the class definition. So after open Model I have
an instance M of my class and everything takes a parameter M, e.g., the class DECIDABLE M of
decidable members of M is defined. Now I want to use some of these things that I defined "outside" the
class (so they take a parameter M) to define * (which is built into the class). Of course I could define it
outside the class but then I would have product M x y instead of x*y and I don't think I can use infix notation
then (If I could that would be fine). Of course if I "knew then what i know now" I would have done a few
more things inside the class; but now I have hundreds of uses of those things. Does anyone have a helpful
suggestion, eg. a way to use infix notation for product M x y ?

If this were C++ the answer would be, make it a virtual function.

Mario Carneiro (Feb 16 2021 at 02:13):

There is no relation between infix notation and being defined inside the class

Mario Carneiro (Feb 16 2021 at 02:14):

infix mul is provided by the has_mul M typeclass, which you can prove after the definition with an instance

Mario Carneiro (Feb 16 2021 at 02:16):

Now I want to use some of these things that I defined "outside" the class (so they take a parameter M) to define * (which is built into the class).

This is a contradiction: if it's built into the class, then it's not defined, it's a field of the structure

Mario Carneiro (Feb 16 2021 at 02:16):

I think an #mwe would help here

Michael Beeson (Feb 16 2021 at 05:09):

class  Model (M:Type) :=
(mul:M  M  M)
(infix * := mul)
(zero:M)
(f:M  M  M)
(f_definition: (x y:M), f x y = zero)
-- (multiplication_definition:∀ (x y:M), x*y = zero)
--I do not want to define it here!
 /- end of class definition because next line doesn't declare a member -/

variables (M:Type) [Model M] (a b x y: M)
open Model
infix * := mul

def mul(a b:M) [M] := f a b
--Can I get away with defining it here and still use infix?

lemma test:  (x y:M), x*y = zero:=
  assume x y,
  begin
    -- rw multiplication_definition,
    --  can I finish this proof using the def of mul?
  end

Mario Carneiro (Feb 16 2021 at 05:19):

class Model (M : Type) :=
(zero : M)
(f : M  M  M)
(f_definition (x y : M) : f x y = zero)

variables (M : Type) [Model M] (a b x y: M)
open Model
instance Model.has_mul : has_mul M := f

lemma mul_def (x y : M) : x * y = f x y := rfl

lemma test (x y : M) : x * y = zero :=
begin
  rw mul_def,
  rw f_definition,
end

Michael Beeson (Feb 16 2021 at 06:01):

Thank you Mario, it's the has_mul line that I was missing. But I also do not understand 'rfl'. I previously thought 'rfl' means, reduce the two sides of an equality and if you get the same normal form that counts as a proof, if not the tactic fails. Here, however, evidently something else is happening. You call mul_def a lemma but it's really just defining what * means. So are we just telling Lean, reduce x*y to f x y?

Mario Carneiro (Feb 16 2021 at 06:12):

no, it does exactly as you say, it reduces both sides to a normal form. mul_def isn't the definition, Model.has_mul is

Mario Carneiro (Feb 16 2021 at 06:15):

Specifically, Model.has_mul says "hey lean, when you need to prove has_mul M, try Model.has_mul M", and when you write x * y it actually means @has_mul.mul M _ x y where _ is a proof of has_mul M; lean will follow the above advice, and so you end up with

@has_mul.mul M (Model.has_mul M) x y

and since Model.has_mul M is defined to be ⟨f⟩ and has_mul.mul is defined to be projection out of this single-element class, the whole thing reduces to f x y, which is why rfl proves mul_def.

Michael Beeson (Feb 16 2021 at 07:33):

OK, I think I've understood your example. Here's one with one more feature, the definition of multiplication can depend on M.

class Model (M : Type) :=
(zero : M)
(f : M  M  M)
(f_definition (x y : M) : f x y = zero)

variables (M : Type) [Model M] (a b x y: M)
open Model

def foo (a b:M):M := f a b

instance Model.has_mul : has_mul M := foo M

lemma mul_def (x y : M) : x * y = f x y := rfl


lemma test (x y : M) : x * y = zero :=
begin
  rw mul_def,
  rw f_definition,
end

Michael Beeson (Feb 16 2021 at 07:44):

Wel

Mario Carneiro (Feb 16 2021 at 07:54):

The definition already depended on M; f is actually @Model.f M _ where _ is an instance of type Model M

Mario Carneiro (Feb 16 2021 at 07:56):

The difference is that M is an implicit argument in f and explicit in foo, which you can see if you print the types:

#print f
-- def Model.f : Π {M : Type} [c : Model M], M → M → M :=

#print foo
-- def foo : Π (M : Type) [_inst_1 : Model M], M → M → M :=

Mario Carneiro (Feb 16 2021 at 07:58):

You can (and should) make M implicit in foo by setting the binder of M in the variables line:

variables {M : Type} [Model M] (a b x y: M)
open Model

def foo (a b:M):M := f a b
#print foo
-- def foo : Π {M : Type} [_inst_1 : Model M], M → M → M :=

instance Model.has_mul : has_mul M := foo

lemma mul_def (x y : M) : x * y = f x y := rfl

Michael Beeson (Feb 16 2021 at 08:09):

Ah, (need light-bulb-over-the-head emoji) just by changing () to {} I could have avoided typing hundreds of explicit Ms.

Michael Beeson (Feb 16 2021 at 08:09):

I didn't think that variables line was doing anything to speak of as I freely use variables that are not in that list and nothing goes wrong.

Mario Carneiro (Feb 16 2021 at 08:34):

The variables line supplies variables automatically if you use them in a statement; but you have to either have declared the variable in a variables line or in the lemma statement itself. For example, the (x y : M) in mul_def are redundant because otherwise it would pick up x y : M from the (a b x y: M) in the variables, but if you used z in mul_def it would be an error, because z was never declared, either in the variables line or in the lemma arguments


Last updated: Dec 20 2023 at 11:08 UTC