我需要帮助在Coq中定义串联

时间:2016-03-11 18:49:58

标签: coq

我需要定义一个连接函数,首先是一些上下文,我定义了set“accept”

Inductive accepts : Set :=
    | True  : accepts
    .
    .
    .
    | fun_m : accepts -> accepts -> accepts
    | n_fun : nat -> accepts -> accepts
    .

然后我需要能够操作一个非常特定的接受子集:列表中的第一个和最后一个,所以只有True和n_fun。我这样做的是归纳和记录的混合:

Inductive n_sub : accepts -> Prop :=
  | a1 : n_sub True
  | a2 : forall (n : nat )(A : accepts), n_sub A -> n_sub (n_fun n A).

Record sub : Set := mk_s{ A : accepts ; WS : (s_sub A)}.

正如你可能会看到的那样,这将给我一串自然数字,后面跟着True,专属,所以我想处理产生n ... k True的接受子集。考虑我有两个这样的字符串,我想定义将“ab ... True”和“xy ... True”发送到“ab ... xy ... True”的函数。

Fixpoint concatenate (A0 A1 : accepts)(x : n_sub A0)(y: n_sub A1):accepts:=
  match x, y with 
    | a1, q => B
    | a2 n A0 x, y => (n_fun n (concatenate A0 A1) )
  end.

显然,这不起作用......我尝试了100种变体:直接使用接受并将内容发送到void,使用里面的记录,在不同的变化中混合接受和sub等等...我只是出于想法,需要有人帮我修好这个连接,拜托!提前感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

有时编写可计算的谓词而不是归纳谓词(我的ok,下面的,与n_sub相比)是有帮助的。

Inductive accepts :=
| valid  : accepts
| fun_m : accepts -> accepts -> accepts
| n_fun : nat -> accepts -> accepts.

Fixpoint ok x :=
  match x with
    | valid => true
    | n_fun _ y => ok y
    | _ => false
  end.

由于ok是可计算的,你可以将它用于以后的各种事情,但你也可以在证明中使用它(见下文)。

Fixpoint concat x y :=
  match x with
    | valid => y
    | n_fun z zs => n_fun z (concat zs y)
    | _ => y
  end.
concat输入的

ok平底船。稍后,我会展示更严格类型的版本concatLegit

Lemma concatOk :
  forall x y,
    ok x = true -> ok y = true -> ok (concat x y) = true.
induction x; auto.
Qed.

Definition legit := { x : accepts & ok x = true }.

Definition concatLegit (x y : legit) : legit.
destruct x as [x p]; destruct y as [y q].
exists (concat x y).
apply concatOk; auto.
Defined.

Print concatLegit.

(*

concatLegit =
fun x y : legit =>
let (x0, p) := x in
let (y0, q) := y in
existT (fun x1 : accepts => ok x1 = true) (concat x0 y0) (concatOk x0 y0 p q)
     : legit -> legit -> legit

*)

答案 1 :(得分:0)

这里的问题是,您尝试对类型为Prop的事物进行模式匹配,以生成accepts类型的Set。 Coq的类型系统不允许这样做。你需要做的是对accepts类型的事物进行模式匹配,然后使用属性来消除不可能的情况。

这里我将使用交互模式。这允许我只使用refine定义我感兴趣的计算部分,并留下空白(使用_)我将在稍后处理的部分。

由于在检查A0时可能会显示一些不相关的分支,因此我需要概括返回类型:我将构建accepts其中n_sub a -> accepts的证据,而不是构建a。 1}}是匹配的A0

Fixpoint concatenate (A0 A1 : accepts)(x : n_sub A0)(y: n_sub A1):accepts.
refine
  ((match A0 as a return n_sub a -> accepts with
    | True        => fun _      => A1
    | n_fun n A0' => fun Hn_fun => n_fun n (concatenate A0' A1 _ y)
    | _ => _
  end) x).

我现在剩下两个证明:我需要定义我留空的情况,但这很容易:假设n_sub (fun_m a a0)是矛盾的!我可以通过反转来证明False

- intro Hf; apply False_rec; inversion Hf.

现在,我必须证明n_sub A0'在假设Hn_fun成立n_sub (n_fun n A0')的情况下保持不变。再一次inversion可以解决问题:

- inversion Hn_fun; assumption.

就是这样!这里棘手的部分是确定需要概括的假设,并在dependent pattern-matching中使用适当的as ... return ...。通过使用交互模式和refine的帮助来构建不完整的证明术语,其余部分非常方便。