Coq:"镜片在组合物下关闭"

时间:2018-01-05 14:33:48

标签: functional-programming coq proof lenses

我是一名全新的Coq功能程序员。事实上,我刚刚完成Mike Naha's tutorial。特别是,我对这种语言感兴趣,以形成一些与光学相关的法律。例如,我想知道如何编码lens is closed under composition

我开始处理 GetPut 。上述教程并未涵盖记录,但我认为它们是我对镜头进行编码所需要的。据我所知,组合方法应该实现为 Definition 。最后,我假设我的定理需要为构图镜头接收 GetPut 的证据,以证明相同的法则通过相等的方式适用于所得到的镜头。不是很有帮助,但这是我的(不完整和错误的)证明框架:

Record lens (S : Type) (A : Type) := mkLens {
  get : S -> A;
  put : S -> A -> S }.

Definition compose_ln (S A B : Type) (ln1: lens S A) (ln2 : lens A B) : lens S B :=
  {| get := fun (s : S) => get ln1 s;
     put := fun (s : S) (a : A) => put ln1 s (put ln2 (get ln1 s) a) |}.

Theorem closed_GetPut :
    (forall S A B : Type,
    (forall (s : S),
    (forall (ln1 : lens S A) (ln2 : lens A B),
    (exists GetPut_proof : ln1 (* ln1 holds GetPut? *)),
    (exists GetPut_proof : ln2 (* ln2 holds GetPut? *)),
    (put (compose_ln ln1 ln2) s (get (compose_ln ln1 ln2) s) = s)))).
Proof.
  (* ... *)
Qed.

这么说:

  • 我是否正确地写这个证据?有没有其他方法可以更好地接近它?
  • 我在哪里可以找到类似的例子作为指导性示例?
  • 根据我的FP背景,继续学习Coq的材料是什么? (我正在考虑Benjamin C. Pierce的Software Foundations。)

谢谢!

2 个答案:

答案 0 :(得分:4)

这看起来大致合理,但需要一些整理。

首先,你不妨删除两个“存在”量词(将它们改为普通含义)。

其次,最后两个假设的类型不应该只是“ln1”和“ln2”,而是类似“very_well_behaved ln1”和“very_well_behaved ln2”。 (然后最终结果的类型可以是“very_well_behaved(compose ln2 ln2)”。

答案 1 :(得分:2)

在阅读Logical Foundations的第一章后(如果你的背景是功能,我肯定会推荐)我能够在Coq中实现镜头关闭的证明。首先,我们需要定义lenscompose

Record lens (S A : Type) := {
  get : S -> A;
  put : S -> A -> S }.

Definition compose {S A B : Type} (ln1 : lens S A) (ln2 : lens A B) : lens S B :=
  {| get := fun (s : S) => ln2.(get A B) (ln1.(get S A) s);
     put := fun (s : S) (b : B) => ln1.(put S A) s (ln2.(put A B) (ln1.(get S A) s) b) |}.

(*)请注意访问记录字段的固定语法。

然后,我们需要声明所涉及的属性,最终达到very_well_behaved(@Benjamin Pierce在接受的答案中建议):

Definition get_put {S A : Type} (ln : lens S A) : Prop :=
  forall (s : S), ln.(put S A) s (ln.(get S A) s) = s.

Definition put_get {S A : Type} (ln : lens S A) : Prop :=
  forall (s : S) (a : A), ln.(get S A) (ln.(put S A) s a) = a.

Definition put_put {S A : Type} (ln : lens S A) : Prop :=
  forall (s : S) (a1 : A) (a2 : A), 
    ln.(put S A) (ln.(put S A) s a1) a2 = ln.(put S A) s a2.

Definition very_well_behaved {S A : Type} (ln : lens S A) : Prop :=
  get_put ln /\ put_get ln /\ put_put ln.

一旦确定了属性,下一个(也是最大的)挑战在于证明表现良好的镜片在成分下是封闭的。为此,我们可以使用以下定理框架:

Theorem compose_is_closed : forall (S A B : Type) (ln1 : lens S A) (ln2 : lens A B),
    very_well_behaved ln1 -> very_well_behaved ln2 -> very_well_behaved (compose ln1 ln2).
Proof.
  (* tactics here *)
Qed.

现在,我的Coq知识非常有限,这就是为什么我不在这里包含策略,因为我觉得我目前的实施仍然是天真的。无论如何,如果你对此感到好奇,你可以找到完整的证据in this gist