Why does Coq include let-expressions in its core languageTheorem Proofs in CoqCan coq express its own metatheory?Collection of inference rules viewed itself as a judgmentLocal type argument synthesis when type variable does not appear in argumentsPure type systems and let-expressionsUnderstanding the definition of Positivity Constraints in CoqHow does this use of “apply” in Coq work?Drawbacks of adding type equality to 1MLDoes dependent type checkers need to store lambda parameter type in their core language?For proof automation in Coq, when is it appropriate to use canonical structures or Equations instead of Ltac?

How was the Luftwaffe able to destroy nearly 4000 Soviet aircraft in 3 days of operation Barbarossa?

What was the sound coming from below the feet of the Death Eaters at Malfoy Manor?

Why does the B-2 Spirit have a pattern of thin white lines?

What is the difference between chemical equilibrium and dynamic equilibrium?

This Riley Riddle is a Mess

What instructions should I give to an untrained passenger for Hand propping Cessna 172N as a pilot?

Difference between apply and funcall

What antenna is this in an Apollo 15 LM photo?

Quantum circuits explain algorithms, why didn't classical circuits?

How can I swallow pills more easily?

Are we experiencing lower level of gravity now compared to past?

Conditional proof demonstration

Short story from the 70s(?) about aliens/angels destroying humankind, from the point of view of a priest/pastor

Is this a reasonable magic pet?

Perfect pitch on only one instrument?

How would a medieval village protect themselves against dinosaurs?

How can I make sure a string contains at least one uppercase letter, one lowercase letter, one number and one punctuation character?

Is there a way to determine what kind of data is sitting in the Redo Queue for an AlwaysOn AG Secondary Replica?

How can I convince my child to write?

How to end sending data over I2C by Slave or Master?

How do the different seasons work for Eladrin?

Balancing empathy and deferring to the syllabus in teaching responsibilities

Is military allowed to wear civilian clothes when testifying in Congress?

What are these color strips for?



Why does Coq include let-expressions in its core language


Theorem Proofs in CoqCan coq express its own metatheory?Collection of inference rules viewed itself as a judgmentLocal type argument synthesis when type variable does not appear in argumentsPure type systems and let-expressionsUnderstanding the definition of Positivity Constraints in CoqHow does this use of “apply” in Coq work?Drawbacks of adding type equality to 1MLDoes dependent type checkers need to store lambda parameter type in their core language?For proof automation in Coq, when is it appropriate to use canonical structures or Equations instead of Ltac?






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;









9















$begingroup$


Coq includes let-expressions in its core language.
We can translate let-expressions to applications like this:
let x : t = v in b ~> ((x:t). b) v
I understand that this does not always work because the value v would not be available when typechecking b. However this can be easily fixed by special casing the typechecking of applications of the form ((x:t). b) v. This allows us to remove let-expressions at the cost of a special case while typechecking. Why does Coq include still include let-expressions? Do they have other advantages (besides not needing the special case)?










share|cite|improve this question









$endgroup$










  • 4




    $begingroup$
    Your suggestion sounds like adding a hack to avoid needing let expressions, but there's a) no reason to avoid let expressions and they are also convenient, and b) adding hacks to your core language is not a great idea.
    $endgroup$
    – Derek Elkins
    Sep 11 at 19:02

















9















$begingroup$


Coq includes let-expressions in its core language.
We can translate let-expressions to applications like this:
let x : t = v in b ~> ((x:t). b) v
I understand that this does not always work because the value v would not be available when typechecking b. However this can be easily fixed by special casing the typechecking of applications of the form ((x:t). b) v. This allows us to remove let-expressions at the cost of a special case while typechecking. Why does Coq include still include let-expressions? Do they have other advantages (besides not needing the special case)?










share|cite|improve this question









$endgroup$










  • 4




    $begingroup$
    Your suggestion sounds like adding a hack to avoid needing let expressions, but there's a) no reason to avoid let expressions and they are also convenient, and b) adding hacks to your core language is not a great idea.
    $endgroup$
    – Derek Elkins
    Sep 11 at 19:02













9













9









9


3



$begingroup$


Coq includes let-expressions in its core language.
We can translate let-expressions to applications like this:
let x : t = v in b ~> ((x:t). b) v
I understand that this does not always work because the value v would not be available when typechecking b. However this can be easily fixed by special casing the typechecking of applications of the form ((x:t). b) v. This allows us to remove let-expressions at the cost of a special case while typechecking. Why does Coq include still include let-expressions? Do they have other advantages (besides not needing the special case)?










share|cite|improve this question









$endgroup$




Coq includes let-expressions in its core language.
We can translate let-expressions to applications like this:
let x : t = v in b ~> ((x:t). b) v
I understand that this does not always work because the value v would not be available when typechecking b. However this can be easily fixed by special casing the typechecking of applications of the form ((x:t). b) v. This allows us to remove let-expressions at the cost of a special case while typechecking. Why does Coq include still include let-expressions? Do they have other advantages (besides not needing the special case)?







type-theory dependent-types type-checking coq






share|cite|improve this question













share|cite|improve this question











share|cite|improve this question




share|cite|improve this question










asked Sep 11 at 14:19









LabbekakLabbekak

4431 silver badge8 bronze badges




4431 silver badge8 bronze badges










  • 4




    $begingroup$
    Your suggestion sounds like adding a hack to avoid needing let expressions, but there's a) no reason to avoid let expressions and they are also convenient, and b) adding hacks to your core language is not a great idea.
    $endgroup$
    – Derek Elkins
    Sep 11 at 19:02












  • 4




    $begingroup$
    Your suggestion sounds like adding a hack to avoid needing let expressions, but there's a) no reason to avoid let expressions and they are also convenient, and b) adding hacks to your core language is not a great idea.
    $endgroup$
    – Derek Elkins
    Sep 11 at 19:02







4




4




$begingroup$
Your suggestion sounds like adding a hack to avoid needing let expressions, but there's a) no reason to avoid let expressions and they are also convenient, and b) adding hacks to your core language is not a great idea.
$endgroup$
– Derek Elkins
Sep 11 at 19:02




$begingroup$
Your suggestion sounds like adding a hack to avoid needing let expressions, but there's a) no reason to avoid let expressions and they are also convenient, and b) adding hacks to your core language is not a great idea.
$endgroup$
– Derek Elkins
Sep 11 at 19:02










1 Answer
1






active

oldest

votes


















23

















$begingroup$

It is a common misconception that we can translate let-expresions to applications. The difference between let x : t := b in v and (fun x : t => v) b is that in the let-expression, during type-checking of v we know that x is equal to b, but in the application we do not (the subexpression fun x : t => v has to make sense on its own).



Here is an example:



(* Dependent type of vectors. *)
Inductive Vector A : Type : nat -> Type :=
| nil : Vector 0
| cons : forall n, A -> Vector n -> Vector (S n).

(* This works. *)
Check (let n := 0 in cons n 42 nil).

(* This fails. *)
Check ((fun (n : nat) => cons n 42 nil) 0).


Your suggestion to make application (fun x : t => v) b a special case does not really work. Let us think about it more carefully.



For example, how would you deal with this, continuing the above example?



Definition a := (fun (n : nat) => cons n 42 nil).
Check a 0.


Presumably this will not work because a cannot be typed, but if we unfold its definition, we get a well-typed expression. Do you think the users will love us, or hate us for our design decision?



You need to think carefully what it means to have the "special case". If I have an application e₁ e₂, should I normalize e₁ before I decide whether it is a $lambda$-abstraction? If yes, this means I will be normalizing ill-typed expressions, and those might cycle. If no, the usability of your proposal seems questionable.



You would also break the fundamental theorem which says that every sub-expression of a well-typed expression is well-typed. That's as sensible as introducing null into Java.






share|cite|improve this answer












$endgroup$
















    Your Answer








    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "419"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );














    draft saved

    draft discarded
















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcs.stackexchange.com%2fquestions%2f114640%2fwhy-does-coq-include-let-expressions-in-its-core-language%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown


























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    23

















    $begingroup$

    It is a common misconception that we can translate let-expresions to applications. The difference between let x : t := b in v and (fun x : t => v) b is that in the let-expression, during type-checking of v we know that x is equal to b, but in the application we do not (the subexpression fun x : t => v has to make sense on its own).



    Here is an example:



    (* Dependent type of vectors. *)
    Inductive Vector A : Type : nat -> Type :=
    | nil : Vector 0
    | cons : forall n, A -> Vector n -> Vector (S n).

    (* This works. *)
    Check (let n := 0 in cons n 42 nil).

    (* This fails. *)
    Check ((fun (n : nat) => cons n 42 nil) 0).


    Your suggestion to make application (fun x : t => v) b a special case does not really work. Let us think about it more carefully.



    For example, how would you deal with this, continuing the above example?



    Definition a := (fun (n : nat) => cons n 42 nil).
    Check a 0.


    Presumably this will not work because a cannot be typed, but if we unfold its definition, we get a well-typed expression. Do you think the users will love us, or hate us for our design decision?



    You need to think carefully what it means to have the "special case". If I have an application e₁ e₂, should I normalize e₁ before I decide whether it is a $lambda$-abstraction? If yes, this means I will be normalizing ill-typed expressions, and those might cycle. If no, the usability of your proposal seems questionable.



    You would also break the fundamental theorem which says that every sub-expression of a well-typed expression is well-typed. That's as sensible as introducing null into Java.






    share|cite|improve this answer












    $endgroup$



















      23

















      $begingroup$

      It is a common misconception that we can translate let-expresions to applications. The difference between let x : t := b in v and (fun x : t => v) b is that in the let-expression, during type-checking of v we know that x is equal to b, but in the application we do not (the subexpression fun x : t => v has to make sense on its own).



      Here is an example:



      (* Dependent type of vectors. *)
      Inductive Vector A : Type : nat -> Type :=
      | nil : Vector 0
      | cons : forall n, A -> Vector n -> Vector (S n).

      (* This works. *)
      Check (let n := 0 in cons n 42 nil).

      (* This fails. *)
      Check ((fun (n : nat) => cons n 42 nil) 0).


      Your suggestion to make application (fun x : t => v) b a special case does not really work. Let us think about it more carefully.



      For example, how would you deal with this, continuing the above example?



      Definition a := (fun (n : nat) => cons n 42 nil).
      Check a 0.


      Presumably this will not work because a cannot be typed, but if we unfold its definition, we get a well-typed expression. Do you think the users will love us, or hate us for our design decision?



      You need to think carefully what it means to have the "special case". If I have an application e₁ e₂, should I normalize e₁ before I decide whether it is a $lambda$-abstraction? If yes, this means I will be normalizing ill-typed expressions, and those might cycle. If no, the usability of your proposal seems questionable.



      You would also break the fundamental theorem which says that every sub-expression of a well-typed expression is well-typed. That's as sensible as introducing null into Java.






      share|cite|improve this answer












      $endgroup$

















        23















        23











        23







        $begingroup$

        It is a common misconception that we can translate let-expresions to applications. The difference between let x : t := b in v and (fun x : t => v) b is that in the let-expression, during type-checking of v we know that x is equal to b, but in the application we do not (the subexpression fun x : t => v has to make sense on its own).



        Here is an example:



        (* Dependent type of vectors. *)
        Inductive Vector A : Type : nat -> Type :=
        | nil : Vector 0
        | cons : forall n, A -> Vector n -> Vector (S n).

        (* This works. *)
        Check (let n := 0 in cons n 42 nil).

        (* This fails. *)
        Check ((fun (n : nat) => cons n 42 nil) 0).


        Your suggestion to make application (fun x : t => v) b a special case does not really work. Let us think about it more carefully.



        For example, how would you deal with this, continuing the above example?



        Definition a := (fun (n : nat) => cons n 42 nil).
        Check a 0.


        Presumably this will not work because a cannot be typed, but if we unfold its definition, we get a well-typed expression. Do you think the users will love us, or hate us for our design decision?



        You need to think carefully what it means to have the "special case". If I have an application e₁ e₂, should I normalize e₁ before I decide whether it is a $lambda$-abstraction? If yes, this means I will be normalizing ill-typed expressions, and those might cycle. If no, the usability of your proposal seems questionable.



        You would also break the fundamental theorem which says that every sub-expression of a well-typed expression is well-typed. That's as sensible as introducing null into Java.






        share|cite|improve this answer












        $endgroup$



        It is a common misconception that we can translate let-expresions to applications. The difference between let x : t := b in v and (fun x : t => v) b is that in the let-expression, during type-checking of v we know that x is equal to b, but in the application we do not (the subexpression fun x : t => v has to make sense on its own).



        Here is an example:



        (* Dependent type of vectors. *)
        Inductive Vector A : Type : nat -> Type :=
        | nil : Vector 0
        | cons : forall n, A -> Vector n -> Vector (S n).

        (* This works. *)
        Check (let n := 0 in cons n 42 nil).

        (* This fails. *)
        Check ((fun (n : nat) => cons n 42 nil) 0).


        Your suggestion to make application (fun x : t => v) b a special case does not really work. Let us think about it more carefully.



        For example, how would you deal with this, continuing the above example?



        Definition a := (fun (n : nat) => cons n 42 nil).
        Check a 0.


        Presumably this will not work because a cannot be typed, but if we unfold its definition, we get a well-typed expression. Do you think the users will love us, or hate us for our design decision?



        You need to think carefully what it means to have the "special case". If I have an application e₁ e₂, should I normalize e₁ before I decide whether it is a $lambda$-abstraction? If yes, this means I will be normalizing ill-typed expressions, and those might cycle. If no, the usability of your proposal seems questionable.



        You would also break the fundamental theorem which says that every sub-expression of a well-typed expression is well-typed. That's as sensible as introducing null into Java.







        share|cite|improve this answer















        share|cite|improve this answer




        share|cite|improve this answer








        edited Sep 11 at 19:24

























        answered Sep 11 at 17:11









        Andrej BauerAndrej Bauer

        22.6k1 gold badge51 silver badges91 bronze badges




        22.6k1 gold badge51 silver badges91 bronze badges































            draft saved

            draft discarded















































            Thanks for contributing an answer to Computer Science Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            Use MathJax to format equations. MathJax reference.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcs.stackexchange.com%2fquestions%2f114640%2fwhy-does-coq-include-let-expressions-in-its-core-language%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown









            Popular posts from this blog

            Tamil (spriik) Luke uk diar | Nawigatjuun

            Align equal signs while including text over equalitiesAMS align: left aligned text/math plus multicolumn alignmentMultiple alignmentsAligning equations in multiple placesNumbering and aligning an equation with multiple columnsHow to align one equation with another multline equationUsing \ in environments inside the begintabularxNumber equations and preserving alignment of equal signsHow can I align equations to the left and to the right?Double equation alignment problem within align enviromentAligned within align: Why are they right-aligned?

            Training a classifier when some of the features are unknownWhy does Gradient Boosting regression predict negative values when there are no negative y-values in my training set?How to improve an existing (trained) classifier?What is effect when I set up some self defined predisctor variables?Why Matlab neural network classification returns decimal values on prediction dataset?Fitting and transforming text data in training, testing, and validation setsHow to quantify the performance of the classifier (multi-class SVM) using the test data?How do I control for some patients providing multiple samples in my training data?Training and Test setTraining a convolutional neural network for image denoising in MatlabShouldn't an autoencoder with #(neurons in hidden layer) = #(neurons in input layer) be “perfect”?