Coq中虚拟值的最佳做法

时间:2018-07-27 17:57:11

标签: coq

我发现我经常在编写这样的代码:

  Fixpoint get_fresh w (Γ : Ctx) : Pat w * Ctx:= 
  match w with
  ... 
  | w1 ⊗ w2 => let (p1, Γ1) := get_fresh w1 Γ in
              match Γ ⋓ Γ1 with
              | None  => (dummy_pat _, dummy_ctx)
              | Some Γ' => (p1,Γ')
  end.

将永远不会输入None分支。 (在这里,不可能进入分支,有时我们永远不会在适当的输入上进入分支。)

实现不应返回的虚拟值的最佳方法是什么?

一种简单的方法是简单地声明

Parameter dummy_pat : forall W, Pat W.
Parameter dummy_ctx : Ctx.

但这听起来似乎是一种不好的做法-因为所有用户都知道CtxPat W可能没有居民。 (对于诸如Pat W之类的相关类型尤其如此。)

我可以为dummy_patdummy_ctx给出简单的定义,但是我不希望用户对此分支进行推理。我可以将dummy_patdummy_ctx声明为不透明,但是不透明性很容易反转。

最后,我想我可以将它们声明为sigma类型的投影,但这似乎会造成混淆,并且我不确定它是否解决了这种情况的推理问题。

(请注意,我不想本质上证明使用Program或其他方式无法访问这些分支。我发现这些函数很难编写和使用。)

有什么建议吗?

1 个答案:

答案 0 :(得分:1)

以下声明模块的方法可能具有更好的不透明度保证(但是如果我错了,我将非常有兴趣知道!):

Module Type DummySig.
Parameter dummy_pat : forall W, Pat W.
Parameter dummy_ctx : Ctx.
End DummySig.

Module Import Dummy : DummySig.
Definition dummy_pat := (* some simple definition *)
Definition dummy_ctx := (* some simple definition *)
End Dummy.

说明

Module Import Dummy : DummySig.Module Dummy : DummySig的缩写,后跟Import Dummy.命令后的End Dummy.

Module Dummy : DummySig.声明一个模块类型为(或 signature DummySig的模块,并密封该模块,以便仅在DummySig关于此Dummy模块是可见的。

这是一个强大的抽象边界,它隐藏了所有实现细节。特别是,Parameter中的DummySig使定义在Dummy中不透明,并且Dummy中定义但未出现在DummySig中的标识符根本不可见从模块外部。

据我所知,这种不透明是不可逆的,这是这里的重点。

为了进行比较,声明模块的其他两种方法是:

  • Module M.公开了模块M中的所有内容,因此它主要是一种命名空间。

  • Module M <: MSig.,还公开了M中的所有内容,同时检查它是否实现了签名MSig(通过Module Type MSig.定义),而没有“密封”方面的Module M : Sig.


其他建议的解决方案

您还可以通过模块函子将虚拟变量转换为实际参数...

Module MyProject (Dummy : DummySig).
Import Dummy.

...

或部分;为避免必须传递虚拟变量,类型类可能会有用。

Class Dummy (A : Type) := { dummy : A }.

Section Dummies.
Context `{forall W, Dummy (Pat W)}.
Context `{Dummy Ctx}.

...

最终,我想知道用户能否推理出无法访问的分支是否真的很糟糕。