Zulip Chat Archive
Stream: general
Topic: prefix type ascriptions
Kyle Miller (Sep 24 2021 at 21:51):
Sometimes I've thought a type ascription or cast could be clearer in certain cases if the type came at the beginning rather than at the end like in (x : t)
. I know show t, from x
exists, but it's rather long in comparison, and I don't find it to be very mnemonic for things that aren't proofs. Borrowing an idea from common lisp, a possible alternative is the t, x
.
notation `the `:0 y `, ` x:0 := (x : y)
This isn't anything like a serious proposal. I just thought I'd mention it in case it's interesting to anyone, or in case anyone has other ways of writing the type first.
For example, as a prefix it acts more like a coercion operator:
def foo {α : Type*} (x : α) := the option α, x
Of course, there's no need for new notation for this:
def the (α : Type*) (x : α) := x
def foo {α : Type*} (x : α) := the (option α) x
However, it's sort of nice how notation lets you avoid additional parentheses in both the type and the term.
def foo' := the ℤ, 17 + 20
Kyle Miller (Sep 24 2021 at 21:56):
(In the realm of mnemonic notation, it seems that $
can generally be pronounced as "of", and if one wanted it'd make a reasonable notation:
notation f ` of `:1 a:0 := f a
This goes against a quasi-rule, though, that infix notation should contain non-alphanumeric symbols.)
Eric Wieser (Sep 24 2021 at 22:03):
Note that show
has different elaboration rules to :
, and can prevent lemmas matching if part of the statement.
Mac (Sep 24 2021 at 23:59):
Kyle Miller said:
Sometimes I've thought a type ascription or cast could be clearer in certain cases if the type came at the beginning rather than at the end like in
(x : t)
.
It is important to note that having the type after the term/variable is not purely a stylistic decision. As Lean has dependent types, the type of a declaration has to come after its parameters and the binders keep this ordering for consistency's sake.
-- ex: the parameter needs to precede the `def`'s type
def paradox (p : P) : ~P := ...
-- without a parameter, the signature looks much like a binder
-- thus, binders and type ascriptions follow this order as well
def foo : Int := (0 : Nat)
Kyle Miller (Sep 25 2021 at 00:22):
@Mac It seems you think I'm suggesting replacing :
? I only mean to suggest that every once in a while readability can be improved if the type comes first, and this a possible way to accomplish it.
Also, what does dependent types have to do with this? other than the fact that in dependent type theory there's a x : t
convention? In each binder, neither the variable nor the type can refer to each other, so they could reasonably come in either order. I follow you as far as there being many benefits to having so-called "duality of syntax" where conceptually related things are written the same way.
Mac (Sep 25 2021 at 00:25):
Kyle Miller said:
I follow you as far as there being many benefits to having so-called "duality of syntax" where conceptually related concepts are written the same way.
That was pretty much my whole point. The reason the type comes after a variable in a binder or ascription is so it mirrors the fact that the type comes after a signature in a declaration (the later of which is necessary because of dependent types).
Eric Wieser (Sep 25 2021 at 07:47):
I dispute the claim that dependent types impose a restriction on the order of the grammar
Eric Wieser (Sep 25 2021 at 07:48):
Why couldn't we have
def the vector n 3, of_zeros (the ℕ, n) := ...
Eric Wieser (Sep 25 2021 at 07:49):
I'm not saying it's better, but I don't see where the requirement that variables are introduced to the left of their use comes from
Mario Carneiro (Sep 25 2021 at 08:37):
In some ways it makes more sense to have \lam (the T, x), e
from a binding structure point of view since x
binds in e
but not in T
; putting the variable after the type means that you can add x
to the context reading strictly left to right without having to skip over T
. (In some languages, the lambda is represented internally as lam T (x. e)
to make this binding structure explicit.)
Eric Rodriguez (Sep 25 2021 at 09:27):
I think what Mac was saying is that we can't have c++ style signatures for things due to dependent typing (i.e. no a^n + b^n ≠ c^n theorem flt (a b c : ℕ) (hc : c ≥ 2) (h : a*b*c ≠ 0)
). But I agree with everyone else, I think this notation is nice.
Kyle Miller (Sep 25 2021 at 20:11):
@Mac One could argue that type ascription notation is backwards for dependent type reasons, and having it is a concession to "duality of syntax." You can't write the function def the (α : Type*) (x : α) := x
with reversed arguments.
This might explain why every once in a while there's an expression where I feel like I'd rather put the type first.
Mac (Sep 25 2021 at 21:37):
I agree with everyone here that type ascriptions in the reverse order (i.e., the Nat x
or, what I would like, just Nat x
or Nat(x)
) are useful, and, as @Kyle Miller pointed out, more logical with respect to dependent type theory. I was simply noting the logic behind not doing them that way is likely for "duality of syntax". Since types have to be written after the main signature a def
for DTT, they are as written such in other places (bindings, type ascriptions, etc.) as well.
Kyle Miller (Sep 26 2021 at 02:59):
@Mac Sorry I'm still pulling on this thread about your claim that "as Lean has dependent types, the type of a declaration has to come after its parameters." In DTT, every term has a well-defined type, so there's no need for a type in a declaration. Imagine a bizarro-Lean where terms come after the type in a type ascription. Then this would be a valid way to write a definition:
lemma const (Prop : p q) := p → q → p : λ h _, h
This also has the nice property that you are able to see the type near the :=
Kyle Miller (Sep 26 2021 at 03:03):
(One problem with Nat x
is that pi types have an evaluation rule in Lean, so you wouldn't be able to distinguish that kind of evaluation from a type ascription. You could get Nat(x)
to work if you make whitespace significant, making Nat (x)
parse differently.)
Mac (Sep 26 2021 at 03:04):
@Kyle Miller fair enough -- it would be more accurate to say that, if a declaration it has an explicit type, it has to come after its parameters. Also I would argue that, technically, that type still is coming after its parameters (just, in that case, in the body of the definition :laughing: .
David Thrane Christiansen (Sep 26 2021 at 11:39):
In addition to Common Lisp, Idris also uses the
for type ascription, and it's defined as the Identity function with an explicit type argument.
Eric Wieser (Sep 26 2021 at 12:48):
I think that's exactly what show
is defined as?
Last updated: Dec 20 2023 at 11:08 UTC