努力实现功能扩展

时间:2018-03-28 16:06:47

标签: function coq proof

我已经在Coq编程了几个月了。特别是,我对函数编程证明感兴趣,其中函数出现在各处( optics state monad 等)。从这个意义上讲,处理功能扩展性已成为必不可少的,尽管非常烦人。为了说明这种情况,让我们假设Monad(只有一个法律定义)的简化:

Class Monad (m : Type -> Type) :=
{ ret : forall {X}, X -> m X
; bind : forall {A B}, m A -> (A -> m B) -> m B
}.
Notation "ma >>= f" := (bind ma f) (at level 50, left associativity).

Class MonadLaws m `{Monad m} :=
{ right_id : forall X (p : m X), p >>= ret = p }.

现在,我想证明将几个ret链接到程序p应该等同于同一个程序:

Example ugly_proof :
  forall m `{MonadLaws m} A (p : m A), 
    p >>= (fun a1 => ret a1 >>= (fun a2 => ret a2 >>= ret)) = p.
Proof.
  intros.
  destruct H0 as [r_id].

  assert (J : (fun a2 : A => ret a2 >>= ret) =
              (fun a2 : A => ret a2)).
  { auto using functional_extensionality. }
  rewrite J.

  assert (K : (fun a1 : A => ret a1 >>= (fun a2 : A => ret a2)) =
              (fun a1 : A => ret a1)).
  { auto using functional_extensionality. }
  rewrite K.

  now rewrite r_id.
Qed.

证明是正确的,但迭代assert模式使得它非常麻烦。事实上,当事情变得更加复杂时,它变得不切实际,正如你在this proof中所发现的那样(证明了仿射遍历在组合下是封闭的)。

话虽如此,实施上述证据的最佳方法是什么?是否有任何关于功能扩展性的项目或文章(比this one更容易接近)作为参考?

3 个答案:

答案 0 :(得分:2)

我将稍微概括一下right_id法律:

Require Import Coq.Logic.FunctionalExtensionality.
Generalizable Variables m A.

Lemma right_id_gen `{ml : MonadLaws m} `{p : m A} r :
  r = ret -> p >>= r = p.
Proof. intros ->; apply ml. Qed.

现在我们可以使用后向推理:

Example not_so_ugly_proof `{ml : MonadLaws m} `{p : m A} :
  p >>= (fun a1 => ret a1 >>= (fun a2 => ret a2 >>= ret)) = p.
Proof.
  apply right_id_gen, functional_extensionality; intros.
  apply right_id_gen, functional_extensionality; intros.
  now apply right_id_gen.
Qed.

答案 1 :(得分:2)

采用setoid_rewrite策略的方法(我试图在this answer中展示它):

Require Import Coq.Logic.FunctionalExtensionality.
Require Import Coq.Setoids.Setoid.
Require Import Coq.Classes.Morphisms.

Generalizable All Variables.

Instance pointwise_eq_ext {A B : Type} `(sb : subrelation B RB eq)
  : subrelation (pointwise_relation A RB) eq.
Proof. intros f g Hfg. apply functional_extensionality. intro x; apply sb, (Hfg x). Qed.

Example easy_proof `{ml : MonadLaws m} `{p : m A} :
  p >>= (fun a1 => ret a1 >>= (fun a2 => ret a2 >>= ret)) = p.
Proof. now repeat setoid_rewrite right_id. Qed.  

阅读材料:

答案 2 :(得分:1)

您可以将RHS重写为p >>= ret,然后使用f_equal向后推理,将目标更改为适用(fun _ => ...) = ret的{​​{1}}。

functional_extensionality