Functional programming Coq:证明;镜头在“合成”下关闭;

Functional programming Coq:证明;镜头在“合成”下关闭;,functional-programming,coq,proof,lenses,Functional Programming,Coq,Proof,Lenses,我是一个功能性程序员,对Coq完全陌生。事实上,我刚做完。特别是,我对这种语言感兴趣,它可以形式化一些与光学相关的定律。例如,我想知道如何对其进行编码 我开始处理GetPut。前面提到的教程不包括记录,但我认为它们是我需要编码镜头的东西。据我所知,组合方法应该作为一个定义来实现。最后,我假设我的定理需要接收合成透镜的GetPut证据,以通过等式证明相同的定律适用于合成透镜。不是很有帮助,但这是我的(不完整和错误)证明框架: Record lens (S : Type) (A : Type) :=

我是一个功能性程序员,对Coq完全陌生。事实上,我刚做完。特别是,我对这种语言感兴趣,它可以形式化一些与光学相关的定律。例如,我想知道如何对其进行编码

我开始处理GetPut。前面提到的教程不包括记录,但我认为它们是我需要编码镜头的东西。据我所知,组合方法应该作为一个定义来实现。最后,我假设我的定理需要接收合成透镜的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?(我在想本杰明·C·皮尔斯的作品。)

谢谢大家!

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

首先,您最好删除两个“存在”量词(将它们更改为普通含义)


第二,最后两个假设的类型不应该仅仅是“ln1”和“ln2”,而是类似于“表现非常好的ln1”和“表现非常好的ln2”。(然后最终结果的类型可以是“非常好的表现(合成ln2 ln2)”。

在阅读了的第一章之后(如果你的背景是功能性的,我肯定会推荐),我能够实现透镜在Coq中合成时关闭的证明。首先,我们需要定义
透镜
合成

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) |}.
(*)注意访问记录字段的固定语法

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

一旦定义了属性,下一个(也是最大的)挑战在于证明性能良好的透镜在合成条件下是闭合的。为此,我们可以使用以下定理框架:

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知识非常有限,这就是为什么我没有在这里包括战术,因为我觉得我当前的实现仍然很幼稚。无论如何,如果你对它感到好奇,你可以找到全部证据。

当然,这是一个更好的结构!但是,我现在看不到
非常好的
背后的原因。我的
存在
直觉是基于“hd具有列表非空的证明”一节。它是否表现得非常好
类似于
hd\u never\u fail
(用
GetPut
PutGet
等替换
safety\u-proof
)?我的意思是,它是一个定义吗?你想要的是定义一个属性(即,从镜头到道具的函数)表示镜头表现良好意味着什么。然后,定理变成“如果两个镜头表现良好,那么它们的组合也很好。”看看《软件基础》的第一卷可能是一个非常有效的方法来加速这一切。太好了,我会这样做。非常感谢!我已经发表了一篇博客文章(),在那里我们展示了与这篇文章非常相似的证明,以防你感兴趣。
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.