例如,如果我定义一个从nat到nat的函数,它将是
Definition plusfive(a:nat): nat := a + 5.
但是,我想定义一个函数,其参数是使用“ S”构造函数(即非零)构造的nat,是否可以直接指定为类型?像
Definition plusfive(a: nat.S): nat := a + 5.
(我知道在这种情况下,我还可以添加一个证明a
非零的参数,但我想知道是否有可能直接基于'S'构造函数来命名类型)。
答案 0 :(得分:5)
功能必须完整,因此您必须使用某些子类型而不是nat
,或者添加一个减少输入空间的参数,例如(H: a<>0)
Definition plusfive(a:nat) (H:a<>0) :=
match a as e return a=e -> _ with
| S _ => fun _ => a + 5
| _ => fun H0 => match (H H0) with end
end eq_refl.
但是,已经发现在大型开发中使用这些技巧非常麻烦,并且通常在基本类型上使用完整的函数,这些函数为错误的输入值返回伪值,并证明该函数已被调用具有正确的参数和功能定义。例如,请参见标准库中如何定义除法。
Require Import Nat.
Print div.
div =
fun x y : nat => match y with
| 0 => y
| S y' => fst (divmod x y' 0 y')
end
: nat -> nat -> nat
因此Compute (div 1 0).
给您0
。
令人高兴的是,您可以直接在表达式中使用div
,而不必插入分母为非零的证明。然后在定义了表达式之后, 证明表达式正确,而不是同时进行。