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.