伊莎贝尔的变异性功能

时间:2015-06-08 13:42:04

标签: isabelle

是否可以使用Isabelle证明助手来定义涉及变量arity函数的理论?

例如,我想定义arity n的所有谓词的理论,它们是循环置换不变的。 给定类型T和整数n,  我想定义arity n的所有谓词的理论,其例如验证:P A_1,... A_n< - > P A_n A_2,...,A_n-1。

在Coq中可以使用依赖类型,我想知道是否有办法用Isabelle表达这个?

2 个答案:

答案 0 :(得分:1)

Isabelle / HOL在某种程度上支持具有任意但固定的arity的函数。标准技巧是将函数的arity编码为类型的基数。因此,您实际上只有一个包含固定数量值的参数。当然,函数的所有变量参数都必须取自相同的类型。在您的示例中,循环性要求已经强制执行此操作。

例如,您可以按如下方式定义arity n的不变谓词的类型。

  typedef ('n :: "{one, plus}", 'a) inv_pred 
    = "{P :: ('n ⇒ 'a) ⇒ bool. ∀f. P f ⟷ P (λn. f (n + 1))}"
    morphisms apply_ip Abs_inv_pred
    by blast

在这里,我们将变量arity谓词建模为从索引集'n到元素类型'a的函数的谓词。 'n上的排序约束确保该类型定义操作+1,我们用它来指定移位。我们可以假设+在发生溢出时会回绕,但这也可以在稍后使用类型中的类型约束来完成。

理论Numeral_Type(在~~/src/HOL/Library中的分布中)定义了有限基数的类型,它们被写为文字数字。对它们的添加确实会在溢出的情况下回绕。因此,人们可以写

typ "(5, int) inv_pred"

表示在整数上有5个参数的谓词类型,这些整数在循环排列下是不变的。类似地,类型(100, nat) inv_pred包含arity 100的所有此类谓词。

如果使用普通函数对变量arity参数进行编码,则将函数应用于给定的参数列表没有很好的语法。理论~~/src/HOL/Multivariate_Analysis/Finite_Cartesian_Product定义了向量的('n, 'a) vec类型,也可以在这里使用。不过,你必须为此定义自己的语法,比如apply_ip P [: x1, x2, x3, x4 :]并编写适当的解析器和漂亮的打印机。

但是,Isabelle在类型检查期间无法对类型级别进行计算。因此,您将很难输入类似

的术语
apply_ip P ([: x1, x2 :] ++ [: x3, x4 :])

因为2 + 2与Isabelle / HOL中的4类型不同。

答案 1 :(得分:1)

n类似的方法 - ary函数是这样的:首先,我们定义正自然数的类型:

theory foo
imports Main "~~/src/HOL/Library/Cardinality" "~~/src/Tools/Adhoc_Overloading"
begin

typedef num1 = "UNIV :: unit set"
  by (rule UNIV_witness)

typedef 'n suc = "UNIV :: ('n::finite) option set"
  by (rule UNIV_witness)

instance num1 :: finite
proof
  show "finite (UNIV :: num1 set)"
    unfolding type_definition.univ[OF type_definition_num1]
    using finite by (rule finite_imageI)
qed

instance suc :: (finite) finite
proof
  show "finite (UNIV :: ('n::finite) suc set)"
    unfolding type_definition.univ[OF type_definition_suc]
    using finite by (rule finite_imageI)
qed

setup_lifting type_definition_num1

现在我们定义n ary函数的类型,这些函数采用类型为n的{​​{1}}值,并返回'a作为从{'b获取功能的函数类型{1}}并返回'n ⇒ 'a,以及这些函数的抽象和应用:

'b

添加一些合成糖:

typedef ('a,'n,'b) nary_fun = "UNIV :: (('n::finite ⇒ 'a) ⇒ 'b) set"
  by (rule UNIV_witness)

setup_lifting type_definition_suc
setup_lifting type_definition_nary_fun

lift_definition nary_fun_apply_1 :: "('a,num1,'b) nary_fun ⇒ 'a ⇒ 'b" 
  is "λf x. f (λ_. x)" .  

lift_definition nary_fun_apply_suc :: "('a,('n::finite) suc,'b) nary_fun ⇒ 'a ⇒ ('a,'n,'b) nary_fun" 
  is "λ(f::('n option ⇒ 'a) ⇒ 'b) (x::'a) (y::'n ⇒ 'a). f (case_option x y)" .  

lift_definition nary_fun_abs_1 :: "('a ⇒ 'b) ⇒ ('a,num1,'b) nary_fun" 
  is "λf x. f (x ())" .

lift_definition nary_fun_abs_suc :: "('a ⇒ ('a,'n::finite,'b) nary_fun) ⇒ ('a,'n suc,'b) nary_fun" 
  is "λf x. f (x None) (λn. x (Some n))" .

lemma nary_fun_1_beta [simp]: "nary_fun_apply_1 (nary_fun_abs_1 f) x = f x"
  by (simp add: nary_fun_abs_1_def nary_fun_apply_1_def Abs_nary_fun_inverse)

lemma nary_fun_suc_beta [simp]: "nary_fun_apply_suc (nary_fun_abs_suc f) x = f x"
  by (simp add: nary_fun_abs_suc_def nary_fun_apply_suc_def Abs_nary_fun_inverse 
                Abs_suc_inverse Rep_nary_fun_inverse)

现在,您可以编写consts nary_fun_apply :: "('a,('n::finite),'b) nary_fun ⇒ 'a ⇒ 'c" (infixl "$" 90) adhoc_overloading nary_fun_apply nary_fun_apply_1 nary_fun_apply_suc syntax "_nary_fun_abs" :: "pttrns ⇒ 'b ⇒ ('a,'n,'b) nary_fun" ("χ (_). _" 10) translations "χ x y. e" == "CONST nary_fun_abs_suc (λx. (χ y. e))" "χ x. e" == "CONST nary_fun_abs_1 (λx. e)" syntax "_NumeralType" :: "num_token => type" ("_") "_NumeralType1" :: type ("1") translations (type) "1" == (type) "num1" parse_translation {* let fun mk_numtype n = if n = 1 then Syntax.const @{type_syntax num1} else if n < 0 then raise TERM ("negative type numeral", []) else Syntax.const @{type_syntax suc} $ mk_numtype (n - 1) fun numeral_tr [Free (str, _)] = mk_numtype (the (Int.fromString str)) | numeral_tr ts = raise TERM ("numeral_tr", ts); in [(@{syntax_const "_NumeralType"}, K numeral_tr)] end; *} print_translation {* let fun int_of (Const (@{type_syntax num1}, _)) = 1 | int_of (Const (@{type_syntax suc}, _) $ t) = 1 + int_of t | int_of t = raise TERM ("int_of", [t]); fun suc_tr' [t] = let val num = string_of_int (int_of t + 1) handle TERM _ => raise Match; in Syntax.const @{syntax_const "_NumeralType"} $ Syntax.free num end | suc_tr' _ = raise Match; in [(@{type_syntax suc}, K suc_tr')] end; *} syntax "_nary_fun_type" :: "type ⇒ type ⇒ type ⇒ type" ("(_ ^/ _ ⇒/ _)" [15, 16, 15] 15) translations (type) "'a ^ 'n ⇒ 'b" == (type) "('a,'n,'b) nary_fun" - ary函数的类型,其'n类型为'n,并将'a作为'b返回,然后您可以使用'a ^ 'n ⇒ 'b像Lambda抽象和χ之类的函数应用程序:

$

我想安德烈亚斯的配方是否对你更方便,取决于你想要对你的功能做些什么,我猜想。