在模块实现中使用模块签名定义

时间:2018-03-15 22:14:12

标签: coq

我对Coq中的模块不是很熟悉,但是我在最近的一个问题中提出了这个问题。我有以下代码。

Module Type Sig.
Parameter n : nat.
Definition n_plus_1 := n + 1.
End Sig.

Module ModuleInstance <: Sig.
Definition n := 3.
End ModuleInstance.
当我尝试运行n_plus_1时,Coq抱怨End ModuleInstance的定义。我不确定这是否是使用模块的正确方法,但我希望它只使用签名中的定义,它是一个完整的定义,不需要任何其他信息。有可能吗?

2 个答案:

答案 0 :(得分:1)

您需要将您的定义放入单独的&#34;模块函数&#34; (基本上是模块级函数:这些是将其他模块作为参数的模块),因此Sig仅包含参数:

Module Type Sig.
  Parameter n : nat.
End Sig.

(* this is the module functor *)
Module SigUtils (S:Sig).
  Definition n_plus_1 := S.n + 1.
End SigUtils.

Module ModuleInstance <: Sig.
  Definition n := 3.
End ModuleInstance.

Module ModuleInstanceUtils := SigUtils ModuleInstance.

它并不是特别难,但有一个很大的局限性:您不能将任何实用程序用作签名的一部分(例如,使类型签名更短)。另一个限制是您的基本定义和派生定义/属性位于不同的模块中,因此如果您符合参考资格,则必须使用正确的名称。但是,如果您导入模块,则无关紧要。

这是标准库在一些地方遵循的模式;例如,FSetFactsFSetProperties仿函数。

答案 1 :(得分:0)

作为https://stackoverflow.com/a/49322214/53974的替代方法,有时可以使用Include,它支持非常有限的递归链接特殊情况。 就像在该答案中一样,您应该将定义放在模块函子中,但随后可以Include在签名的其余部分和实现模块中使用。这样可以重用您的定义以缩短声明,并将它们作为同一模块的一部分。

Require Import Omega.

Module Type Sig.
  Parameter n : nat.
End Sig.

(* this is the module functor *)
Module SigUtils (S:Sig).
  Definition n_plus_1 := S.n + 1.
End SigUtils.

Module ModuleInstance <: Sig.
  Definition n := 3.
  Include SigUtils.
End ModuleInstance.
Print ModuleInstance.

Module Type Sig2 <: Sig.
  Include Sig.
  Include SigUtils.
  Parameter n_plus_1_eq: n_plus_1 = 1 + n.
End Sig2.

Module ModuleInstance2 <: Sig2.
  Include ModuleInstance.

  Lemma n_plus_1_eq: n_plus_1 = 1 + n.
  Proof. unfold n_plus_1. omega. Qed.

  Lemma n_plus_1_neq: n_plus_1 <> 2 + n.
  Proof. unfold n_plus_1. omega. Qed.
End ModuleInstance2.

Print ModuleInstance2.

但是,您需要提防Include的语义(例如,参见 https://stackoverflow.com/a/49717951/53974)。特别是,如果您将一个模块包含在两个不同的模块中,则会得到不同的定义。上面,SigUtils一次包含在Module Type中,一次包含在实现的Module中,这是允许的。