Подобный способ сделать n
-значных функций заключается в следующем: Во-первых, мы определим типы положительных натуральных чисел:
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
ичных функций, которые принимают n
значения типа 'a
и возвращать 'b
как тип функций, которые принимают functon от 'n ⇒ 'a
и возвращают 'b
и absraction и применение для этих функций:
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)
Добавьте syntatical сахар:
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"
Теперь вы можете написать тип 'n
-ичных функций, которые принимают 'n
значения типа 'a
и возвращают 'b
в 'a^'n ⇒ 'b
, и вы можете использовать χ
как лямбда-абстракции и $
как применение функции:
lemma "(χ x y. (x, y)) $ 1 $ 2 = (1,2)" by simp
term "(χ x y z. (x, y + z))"
(* "χ x y z. (x, y + z)" :: "'a^3 ⇒ 'a × 'a" *)
ли моя формулировка Andreas является более удобным для вас, зависит от того, что именно вы хотите сделать с вашими функциями, Я полагаю.