Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide a way to define top-level definitions #173

Open
Ailrun opened this issue Sep 6, 2024 · 18 comments
Open

Provide a way to define top-level definitions #173

Ailrun opened this issue Sep 6, 2024 · 18 comments
Assignees
Milestone

Comments

@Ailrun
Copy link
Member

Ailrun commented Sep 6, 2024

Without that it is highly cumbersome to give more interesting examples.

@Ailrun Ailrun added this to the Frontend milestone Sep 7, 2024
@Ailrun
Copy link
Member Author

Ailrun commented Sep 7, 2024

A related additional feature: module system

@Ailrun Ailrun pinned this issue Sep 8, 2024
@HuStmpHrrr
Copy link
Member

Let binding in this rule is effectively just top level definition. We can do something like this for now.

IMG20240914180035

@Ailrun
Copy link
Member Author

Ailrun commented Sep 14, 2024

@HuStmpHrrr One issue with that is T' cannot depend on x. For example, if we define a Pair type (by church encoding), we cannot use that type as the result type.

@HuStmpHrrr
Copy link
Member

we should replace x in T' with t.

@Ailrun
Copy link
Member Author

Ailrun commented Sep 14, 2024

We cannot still mention Pair (or so) at the final result type. Otherwise, presupposition ({{ Gamma |- T' : Type@i }}) for {{ Gamma |- let ... in ... : T' }} cannot be true.

@HuStmpHrrr
Copy link
Member

HuStmpHrrr commented Sep 14, 2024

we should replace x in T' with t.

T' can refer to Pair, it's just that it will be expanded. T' sees x as an extra variable.

@Ailrun
Copy link
Member Author

Ailrun commented Sep 15, 2024

I mean T' as the result type. Or, with that substitution, T'[t/x]. Our current impl expects the type that the expression checks against, and that type cannot refer to Pair.

@Ailrun
Copy link
Member Author

Ailrun commented Sep 15, 2024

So, for example, with a "proper" top-level,

def Pair : forall (A : Type@0) (B : Type@0) -> Type@1 =
  fun (A : Type@0) (B : Type@0) -> forall (C : Type@0) (pair : forall (a : A) (b : B) -> C) -> C

def pair : forall (A : Type@0) (B : Type@0) (a : A) (b : B) -> Pair A B =
  fun (A : Type@0) (B : Type@0) (a : A) (b : B) (C : Type@0) (pair : forall (a : A) (b : B) -> C) -> pair a b

pair Nat (forall (x : Nat) -> Nat) 3 (fun (x : Nat) -> succ (succ x)) : Pair Nat (forall (x : Nat) -> Nat)

will be possible, but with that "let" approach,

let Pair = fun (A : Type@0) (B : Type@0) -> forall (C : Type@0) (pair : forall (a : A) (b : B) -> C) -> C in
let pair = fun (A : Type@0) (B : Type@0) (a : A) (b : B) (C : Type@0) (pair : forall (a : A) (b : B) -> C) -> pair a b in
pair Nat (forall (x : Nat) -> Nat) 3 (fun (x : Nat) -> succ (succ x))
  : Pair Nat (forall (x : Nat) -> Nat)

will not be possible (because of the reference to Pair in the type of the entire expression)

@HuStmpHrrr
Copy link
Member

that's because the last column lives outside of the lets. problems like this can always be worked around by fitting the last expression to another layer of let:

...
let foo : Pair Nat (forall (x : Nat) -> Nat) := pair Nat (forall (x : Nat) -> Nat) 3 (fun (x : Nat) -> succ (succ x)) in
0 : Nat

It's not perfect, but passing the typechecker implies foo is also well-typed.

@HuStmpHrrr
Copy link
Member

I am not saying it's perfect, but I would expect a local let binding is implemented in this very same way. It does no harm to use this solution for now.

@Ailrun
Copy link
Member Author

Ailrun commented Sep 15, 2024

I agree on that this solution is easy to implement, and a good temporary solution. What I wanted to say is that there is the abovementioned issue I want to note.

@HuStmpHrrr
Copy link
Member

HuStmpHrrr commented Sep 15, 2024

yeah let's do this and figure out a mechanizable solution for genuine top-level definitions at a later time, which can wait. I think even this solution might induce some downstream optimizations that would complicate the proof.

@HuStmpHrrr
Copy link
Member

I think what I have above won't work. We do need to change the context structure to allow binding a variable to a value. Then the question goes to how the substitution calculus should work. c.f. Coq's let rule https://coq.inria.fr/doc/V8.18.0/refman/language/cic.html#id6 and the Delta-local rule: https://coq.inria.fr/doc/V8.18.0/refman/language/core/conversion.html#delta-reduction-sect

@Ailrun
Copy link
Member Author

Ailrun commented Sep 15, 2024

What would be the problem?

@HuStmpHrrr
Copy link
Member

T' alone might not be well-typed without knowing t, that means we only know T'[t/x] is well-typed but not T', so we cannot apply equivalence of substitutions to it.

@Ailrun
Copy link
Member Author

Ailrun commented Sep 16, 2024

What about the independent version? Although that's identical to the "syntactic sugar" approach Antoine is building (based on lambda and application).

@HuStmpHrrr
Copy link
Member

T' Independent of x? Still the same problem applies for t'. It cannot be well-typed in general without knowing t, so substitution calculus can't apply.

@Ailrun
Copy link
Member Author

Ailrun commented Sep 16, 2024

Ah true. Yeah we need a proper top-level definition.

@Ailrun Ailrun unpinned this issue Sep 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants