Dot notation
Say you have a type, like Subgroup G
, and a term of that type, like H : Subgroup G
. Say you have a function in the Subgroup
namespace which takes as input a term of type Subgroup G
, for example Subgroup.inv_mem
, which has as an explicit input a term H : Subgroup G
and spits out a proof that x ∈ H → x⁻¹ ∈ H
. Then instead of writing Subgroup.inv_mem H : x ∈ H → x⁻¹ ∈ H
you can just write H.inv_mem : x ∈ H → x⁻¹ ∈ H
.
In general the rule is that if you have a term H : Foo ...
of type Foo
or Foo A B
or whatever, and then you have a function called Foo.bar
which has an explicit (i.e., round brackets) input of type Foo ...
, then instead of Foo.bar H
you can just write H.bar
. This is why it’s a good idea to define theorems about Foo``s in the ``Foo
namespace.
This sort of trick can be used all over the place; it’s surprisingly powerful. For example Lean has a proof Eq.symm : x = y → y = x
. If you have a term h : a = b
then, remembering that =
is just notation for Eq
so that h
really has type Eq a b
, you can write h.symm : b = a
as shorthand for Eq.symm h
.