在我真正尝试使用它之前,它看起来绝对是一项简单的任务。我的方法是使用双指针以避免提前询问列表的长度,但困难来自于我确信一个列表比另一个列表“没有空闲”的暗示。具体来说,在伪coq中:
Definition twin_ptr (heads, tail, rem : list nat) :=
match tail, rem with
| _, [] => (rev heads, tail)
| _, [_] => (rev heads, tail)
| t :: tl, _ :: _ :: rm => twin_ptr (t :: heads) tl rm
end.
Definition split (l : list nat) := twin_ptr [] l l
但是肯定不会编译因为匹配案例不完整。但是,构建中缺失的案例不存在。
你实施它的方式是什么?
答案 0 :(得分:2)
您不需要维护第二个列表大于第三个列表的不变量。这是一个可能的解决方案:
<input #checkbox1 type="checkbox" [checked]="true" (change)="onChange(1, checkbox1)"/>{{name1}}
<br>
<input #checkbox2 type="checkbox" (change)="onChange(2, checkbox2)"/>{{name2}}
答案 1 :(得分:2)
我不害怕依赖类型,您可以添加rem
短于tail
的证明作为twin_ptr
的参数。使用Program
来帮助管理这些依赖类型,可以提供以下内容。
Require Import List. Import ListNotations.
Require Import Program.
Require Import Arith.
Require Import Omega.
Program Fixpoint twin_ptr
(heads tail rem : list nat)
(H:List.length rem <= List.length tail) :=
match tail, rem with
| a1, [] => (rev heads, tail)
| a2, [a3] => (rev heads, tail)
| t :: tl, _ :: _ :: rm => twin_ptr (t :: heads) tl rm _
| [], _::_::_ => !
end.
Next Obligation.
simpl in H. omega.
Qed.
Next Obligation.
simpl in H. omega.
Qed.
Definition split (l : list nat) := twin_ptr [] l l (le_n _).
感叹号表示分支无法访问。
然后,您可以证明twin_ptr
的引理,并从中推断出split
的属性。例如,
Lemma twin_ptr_correct : forall head tail rem H h t,
twin_ptr head tail rem H = (h, t) ->
h ++ t = rev head ++ tail.
Proof.
Admitted.
Lemma split_correct : forall l h t,
split l = (h, t) ->
h ++ t = l.
Proof.
intros. apply twin_ptr_correct in H. assumption.
Qed.
就个人而言,我不喜欢在函数中使用依赖类型,因为生成的对象更难以操作。相反,我更喜欢定义总函数,并在引理中给出正确的假设。
答案 2 :(得分:0)
我建议采用更精确的类型吗?主要思想是定义一个函数,将Vector.t
索引的形状为nat
的{{1}}分成m + n
大小为Vector.t
,其中一个大小为{{} 1}}。
m
完成此操作后,您已将问题缩小为定义n
的{{1}}和Require Import Vector.
Definition split_vector : forall a m n,
Vector.t a (m + n) -> (Vector.t a m * Vector.t a n).
Proof.
intros a m n; induction m; intro v.
- firstorder; constructor.
- destruct (IHm (tl v)) as [xs ys].
firstorder; constructor; [exact (hd v)|assumption].
Defined.
,并证明它们总和为floor
。
ceil
确实,您可以将n / 2
转换为n
并使用Fixpoint div2_floor_ceil (n : nat) : (nat * nat) := match n with
| O => (O , O)
| S O => (O , S O)
| S (S n') => let (p , q) := div2_floor_ceil n'
in (S p, S q)
end.
Definition div2_floor (n : nat) := fst (div2_floor_ceil n).
Definition div2_ceil (n : nat) := snd (div2_floor_ceil n).
Lemma plus_div2_floor_ceil : forall n, div2_floor n + div2_ceil n = n.
Proof.
refine
(fix ih n := match n with
| O => _
| S O => _
| S (S n') => _
end); try reflexivity.
unfold div2_floor, div2_ceil in *; simpl.
destruct (div2_floor_ceil n') as [p q] eqn: eq.
simpl.
replace p with (div2_floor n') by (unfold div2_floor ; rewrite eq ; auto).
replace q with (div2_ceil n') by (unfold div2_ceil ; rewrite eq ; auto).
rewrite <- plus_n_Sm; do 2 f_equal.
apply ih.
Qed.
获取每个部分。
length xs