我尝试将coq用作具有依赖类型的编程语言。我创建了以下小程序:
Inductive Good : list nat -> Set :=
| GoodNonEmpty : forall h t, Good (h :: t).
Definition get_first(l : list nat)(good : Good l) : nat :=
match l with
| h :: t => h
| nil =>
match good with
end
end.
我为非空列表定义了一个类型,并创建了一个函数,它获取了这样一个列表的第一个元素,前提是它有一个非空的证据。我处理好头部项目由两个项目组成的情况,但我无法处理空列表的不可能的情况。我怎样才能在coq中做到这一点?
答案 0 :(得分:6)
比您尝试更简单的一种方法是:
Definition get_first (l : list nat) (good : Good l) : nat :=
match good with
| GoodNonEmpty h _ => h
end.
这是一种以您想要的方式执行此操作的方法。您会注意到,证明" Good nil"非常啰嗦内联不存在。
Definition get_first (l : list nat) (good : Good l) : nat :=
(
match l as l' return (Good l' -> nat) with
| nil =>
fun (goodnil : Good nil) =>
(
match goodnil in (Good l'') return (nil = l'' -> nat) with
| GoodNonEmpty h t =>
fun H => False_rect _ (nil_cons H)
end
)
(@eq_refl _ nil)
| h :: _ => fun _ => h
end
) good.
你可以肯定地在外面定义一些并重复使用它。我不知道最好的做法。也许有人可以采用更短的方式来做同样的事情。
编辑:
顺便说一句,你可以在证明模式下以更简单的方式得到几乎相同的结果:
Definition get_first' (l : list nat) (good : Good l) : nat.
Proof.
destruct l. inversion good. exact n.
Defined.
然后你可以:
Print get_first'.
了解Coq如何定义它。但是,对于更复杂的事情,你可能会更好地关注#coq IRC频道提出的解决方案中的gdsfhl:
你可以看到他使用refine
策略来提供要写的术语的骨架的一部分,并推迟丢失的证据。