C'est une idée fausse commune que nous pouvons traduire let
-expresions en applications. La différence entre let x : t := b in v
et (fun x : t => v) b
est que dans l' let
expression-, pendant la vérification de type de v
nous savons que x
est égal à b
, mais dans l'application nous ne le faisons pas (la sous-expression fun x : t => v
doit avoir un sens par elle-même).
Voici un exemple:
(* 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).
Votre suggestion de faire de l'application (fun x : t => v) b
un cas spécial ne fonctionne pas vraiment. Réfléchissons-y plus attentivement.
Par exemple, comment traiteriez-vous cela, en continuant l'exemple ci-dessus?
Definition a := (fun (n : nat) => cons n 42 nil).
Check a 0.
Vraisemblablement, cela ne fonctionnera pas car a
ne peut pas être tapé, mais si nous déplions sa définition, nous obtenons une expression bien typée. Pensez-vous que les utilisateurs vont nous aimer ou nous détester pour notre décision de conception?
Vous devez réfléchir soigneusement à ce que signifie avoir le "cas spécial". Si j'ai une application e₁ e₂
, dois-je normaliser e₁
avant de décider s'il s'agit d'une -abstraction? Si oui, cela signifie que je normaliserai les expressions mal typées, et celles-ci pourraient tourner. Si non, l'utilisabilité de votre proposition semble discutable.λ
Vous briseriez également le théorème fondamental qui dit que chaque sous-expression d'une expression bien typée est bien typée. C'est aussi sensé que d'introduire null
dans Java.
let
expressions, mais il n'y a pas de raison d'éviter leslet
expressions et elles sont également pratiques, et b) l'ajout de hacks à votre langage de base n'est pas une bonne idée.