设计仿函数能够使用不同的模块

时间:2013-04-04 02:37:48

标签: coq

我有两个不同的模块签名到两个不同的文件。它们具有相同的字段名称但行为不同。

里面的functor定义了另一个函子。

PI.v

Module Type TPI.
  Parameter sig : Signature.
  Parameter trsInt: forall f, pi f.
End TPI.

Module P (Export T: TPI).
   Lemma A...
    Module Export Mono <: MonoType.
End P.

MI.v

Module Type TMI.
   Parameter sig : Signature.
   Parameter trsInt : forall f, mi f.
End TMI.

Module M (Export TM: TMI).
   Lemma B ...
   Module Export Mono <: MonoType.
End M.

其他文件中的MonoType位置,例如Mono.v

这是我的情况。

我在该文件中有另一个名为B.v的文件,我需要在文件PI.vMI.v中使用定义和引理。

一个定义我需要使用它们两个例如。

 Definition redPair R is :=
   match is with
 | Type_PI => pi_int R is
 | Type_MI => mi_int R is
 end.

我在R遇到问题,因为pi_int Rmi_int Rsig(签名)不同,其中pi_int使用了trsInt模块签名TPImint_int在模块签名trsInt中使用了TMI

这是我定义它的方式:

Module PI (Import P : TPI).
Definition pi_int R is := P.trsInt ...

(* inside PI I define another functor for MI *)
  Module MI (Import M : TMI).
   Definition mi_int R is := M.trsInt ...

   Definition redPair R is :=  
     match is with
    | Type_PI => pi_int R is
    | Type_MI => mi_int R is  (* error here saying that it used the sig of 
                    P.sig but in this case mi_int used the sig of M.sig *)
    end.

End MI.
End PI.

我的问题是,有没有一种方法可以让我拥有一个良好的模块结构,我可以在定义redPair处拥有相同的签名?谢谢您的帮助。

1 个答案:

答案 0 :(得分:3)

实际上,在redPair的定义中,您无法保证P.sigM.sig具有相同的类型,这就是您收到此错误消息的原因。

解决此类问题的方法是通过“共享约束”强制实现类型相等。以下是与您类似的代码,演示了我如何强制P.sigM.sig等于nat

Module Type TPI.
  Parameter sig : Type.
  Parameter x : sig.
End TPI.

Module Type TMI.
  Parameter sig : Type.
  Parameter x : sig.
End TMI.

Module PI (Import P : TPI with Definition sig := nat).
  Definition pi_int := x.

  Module MI (Import M : TMI with Definition sig := nat).
    Definition mi_int := x.

    Definition f (x : bool) :=
      if x
      then pi_int
      else mi_int.

  End MI.

End PI.

您也可以选择保留P.sig不受约束,但强制执行M.sig是相同的:

Module PI (Import P : TPI).
  Definition pi_int := x.

  Module MI (Import M : TMI with Definition sig := P.sig).
    Definition mi_int := x.

    Definition f (x : bool) :=
      if x
      then pi_int
      else mi_int.

  End MI.

End PI.

既然已经提到了解决问题的方法,我建议您在Coq中使用模块和仿函数时要小心。通常情况下,您实际上只需要依赖记录。模块和仿函数对每个人来说都很复杂,你必须关心抽象,共享约束等等。

现状似乎是你应该避免使用它们,除非你实际上需要它们提供的依赖记录:抽象和/或子类型。

事实上,我现在对你的定义感到有些不安。例如,在MI内定义PI是否有意义?没有更多背景,这似乎是武断的也许它确实如此,我只是说你在使用模块时应该小心,并确保你很好地掌握你正在做的事情,否则它可能适得其反! :)

但如果您只是在尝试,请尝试一下。了解各种可能性以及各自的利弊是很好的。