Es ist ein weit verbreitetes Missverständnis, dass wir letAusdrücke in Anwendungen übersetzen können. Der Unterschied zwischen let x : t := b in vund (fun x : t => v) bbesteht darin, dass wir im letAusdruck während der Typprüfung vwissen, dass dies xgleich bist, in der Anwendung jedoch nicht (der Unterausdruck fun x : t => vmuss für sich genommen Sinn machen).
Hier ist ein Beispiel:
(* 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).
Ihr Vorschlag, die Bewerbung zu (fun x : t => v) beinem Sonderfall zu machen, funktioniert nicht wirklich. Lassen Sie uns genauer darüber nachdenken.
Wie würden Sie zum Beispiel damit umgehen und das obige Beispiel fortsetzen?
Definition a := (fun (n : nat) => cons n 42 nil).
Check a 0.
Vermutlich funktioniert dies nicht, weil aes nicht eingegeben werden kann, aber wenn wir seine Definition entfalten, erhalten wir einen gut typisierten Ausdruck. Glauben Sie, dass die Benutzer uns lieben oder für unsere Designentscheidung hassen werden?
e₁ e₂e₁λ
Sie würden auch den Grundsatz brechen, der besagt, dass jeder Unterausdruck eines gut typisierten Ausdrucks gut typisiert ist. Das ist genauso sinnvoll wie die Einführung nullin Java.
letAusdrücke benötigt werden, aber es gibt a) keinen Grund,letAusdrücke zu vermeiden , und sie sind auch praktisch, und b) das Hinzufügen von Hacks zu Ihrer Kernsprache ist keine gute Idee.