let
式をアプリケーションに変換できるというのはよくある誤解です。との違いはlet x : t := b in v
、-式(fun x : t => v) b
ではlet
、型チェック時にがに等しいv
ことx
がわかってb
いますが、アプリケーションではそうではありません(部分式fun x : t => v
はそれ自体で意味を持つ必要があります)。
次に例を示します。
(* 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).
アプリケーション(fun x : t => v) b
を特別なケースにするというあなたの提案は実際には機能しません。それについてもっと注意深く考えてみましょう。
たとえば、上記の例を続けて、これにどのように対処しますか?
Definition a := (fun (n : nat) => cons n 42 nil).
Check a 0.
a
型付けできないため、おそらくこれは機能しませんが、その定義を展開すると、適切に型付けされた式が得られます。ユーザーは私たちを愛していると思いますか、それとも私たちのデザイン決定を嫌っていますか?
e₁ e₂
e₁
λ
また、型付けされた式のすべての部分式は型付けされているという基本的な定理を破ります。これはnull
、Javaに導入するのと同じくらい賢明です。
let
、式を必要としないようにハックを追加するように聞こえますが、a)let
式を避ける理由はなく、それらも便利です。b)コア言語にハックを追加することは素晴らしいアイデアではありません。