我需要定义一个连接函数,首先是一些上下文,我定义了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等等...我只是出于想法,需要有人帮我修好这个连接,拜托!提前感谢您的帮助!
答案 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
的帮助来构建不完整的证明术语,其余部分非常方便。