feat(kernel/inductive): use nondependent elimination when the datatype is in Bool/Prop
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
45252e2229
commit
28b70b4e04
2 changed files with 45 additions and 12 deletions
|
@ -34,6 +34,7 @@ struct add_inductive_fn {
|
||||||
type_checker m_tc;
|
type_checker m_tc;
|
||||||
|
|
||||||
level m_elim_level; // extra universe level for eliminator.
|
level m_elim_level; // extra universe level for eliminator.
|
||||||
|
bool m_dep_elim; // true if using dependent elimination
|
||||||
|
|
||||||
buffer<expr> m_param_consts; // local constants used to represent global parameters
|
buffer<expr> m_param_consts; // local constants used to represent global parameters
|
||||||
buffer<level> m_it_levels; // the levels for each inductive datatype in m_decls
|
buffer<level> m_it_levels; // the levels for each inductive datatype in m_decls
|
||||||
|
@ -300,6 +301,14 @@ struct add_inductive_fn {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \brief Initialize m_dep_elim flag */
|
||||||
|
void set_dep_elim() {
|
||||||
|
if (m_env.impredicative() && is_zero(m_it_levels[0]))
|
||||||
|
m_dep_elim = false;
|
||||||
|
else
|
||||||
|
m_dep_elim = true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Given t of the form (I As is) where I is one of the inductive datatypes being defined,
|
\brief Given t of the form (I As is) where I is one of the inductive datatypes being defined,
|
||||||
As are the global parameters, and is the actual indices provided to it.
|
As are the global parameters, and is the actual indices provided to it.
|
||||||
|
@ -334,10 +343,14 @@ struct add_inductive_fn {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
info.m_major_premise = mk_local(mk_fresh_name(), "n", mk_app(mk_app(m_it_consts[d_idx], m_param_consts), info.m_indices));
|
info.m_major_premise = mk_local(mk_fresh_name(), "n", mk_app(mk_app(m_it_consts[d_idx], m_param_consts), info.m_indices));
|
||||||
name C("C");
|
expr C_ty = mk_sort(m_elim_level);
|
||||||
|
if (m_dep_elim)
|
||||||
|
C_ty = Pi(info.m_major_premise, C_ty);
|
||||||
|
C_ty = Pi(info.m_indices, C_ty);
|
||||||
|
name C_name("C");
|
||||||
if (get_num_its() > 1)
|
if (get_num_its() > 1)
|
||||||
C = name(C).append_after(d_idx+1);
|
C_name = name(C_name).append_after(d_idx+1);
|
||||||
info.m_C = mk_local(mk_fresh_name(), C, Pi(info.m_indices, Pi(info.m_major_premise, mk_sort(m_elim_level))));
|
info.m_C = mk_local(mk_fresh_name(), C_name, C_ty);
|
||||||
m_elim_info.push_back(info);
|
m_elim_info.push_back(info);
|
||||||
d_idx++;
|
d_idx++;
|
||||||
}
|
}
|
||||||
|
@ -366,8 +379,11 @@ struct add_inductive_fn {
|
||||||
}
|
}
|
||||||
buffer<expr> it_indices;
|
buffer<expr> it_indices;
|
||||||
unsigned it_idx = get_I_indices(t, it_indices);
|
unsigned it_idx = get_I_indices(t, it_indices);
|
||||||
expr intro_app = mk_app(mk_app(mk_app(mk_constant(intro_rule_name(ir), m_levels), m_param_consts), b), u);
|
expr C_app = mk_app(m_elim_info[it_idx].m_C, it_indices);
|
||||||
expr C_app = mk_app(mk_app(m_elim_info[it_idx].m_C, it_indices), intro_app);
|
if (m_dep_elim) {
|
||||||
|
expr intro_app = mk_app(mk_app(mk_app(mk_constant(intro_rule_name(ir), m_levels), m_param_consts), b), u);
|
||||||
|
C_app = mk_app(C_app, intro_app);
|
||||||
|
}
|
||||||
// populate v using u
|
// populate v using u
|
||||||
for (unsigned i = 0; i < u.size(); i++) {
|
for (unsigned i = 0; i < u.size(); i++) {
|
||||||
expr u_i = u[i];
|
expr u_i = u[i];
|
||||||
|
@ -380,8 +396,11 @@ struct add_inductive_fn {
|
||||||
}
|
}
|
||||||
buffer<expr> it_indices;
|
buffer<expr> it_indices;
|
||||||
unsigned it_idx = get_I_indices(u_i_ty, it_indices);
|
unsigned it_idx = get_I_indices(u_i_ty, it_indices);
|
||||||
expr u_app = mk_app(u_i, xs);
|
expr C_app = mk_app(m_elim_info[it_idx].m_C, it_indices);
|
||||||
expr C_app = mk_app(mk_app(m_elim_info[it_idx].m_C, it_indices), u_app);
|
if (m_dep_elim) {
|
||||||
|
expr u_app = mk_app(u_i, xs);
|
||||||
|
C_app = mk_app(C_app, u_app);
|
||||||
|
}
|
||||||
expr v_i_ty = Pi(xs, C_app);
|
expr v_i_ty = Pi(xs, C_app);
|
||||||
expr v_i = mk_local(mk_fresh_name(), name("v").append_after(i), v_i_ty);
|
expr v_i = mk_local(mk_fresh_name(), name("v").append_after(i), v_i_ty);
|
||||||
v.push_back(v_i);
|
v.push_back(v_i);
|
||||||
|
@ -398,7 +417,9 @@ struct add_inductive_fn {
|
||||||
/** \brief Declare elimination rule */
|
/** \brief Declare elimination rule */
|
||||||
void declare_elim_rule(inductive_decl const & d, unsigned d_idx) {
|
void declare_elim_rule(inductive_decl const & d, unsigned d_idx) {
|
||||||
elim_info const & info = m_elim_info[d_idx];
|
elim_info const & info = m_elim_info[d_idx];
|
||||||
expr C_app = mk_app(mk_app(info.m_C, info.m_indices), info.m_major_premise);
|
expr C_app = mk_app(info.m_C, info.m_indices);
|
||||||
|
if (m_dep_elim)
|
||||||
|
C_app = mk_app(C_app, info.m_major_premise);
|
||||||
expr elim_ty = Pi(info.m_indices, Pi(info.m_major_premise, C_app));
|
expr elim_ty = Pi(info.m_indices, Pi(info.m_major_premise, C_app));
|
||||||
// abstract all introduction rules
|
// abstract all introduction rules
|
||||||
unsigned i = get_num_its();
|
unsigned i = get_num_its();
|
||||||
|
@ -428,6 +449,7 @@ struct add_inductive_fn {
|
||||||
|
|
||||||
/** \brief Declare the eliminator/recursor for each datatype */
|
/** \brief Declare the eliminator/recursor for each datatype */
|
||||||
void declare_elim_rules() {
|
void declare_elim_rules() {
|
||||||
|
set_dep_elim();
|
||||||
mk_elim_level();
|
mk_elim_level();
|
||||||
mk_elim_info();
|
mk_elim_info();
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
|
|
|
@ -29,7 +29,7 @@ env = add_inductive(env,
|
||||||
-- 1 is the number of parameters.
|
-- 1 is the number of parameters.
|
||||||
-- The Boolean true in {A, U_l, true} is marking that this argument is implicit.
|
-- The Boolean true in {A, U_l, true} is marking that this argument is implicit.
|
||||||
env = add_inductive(env,
|
env = add_inductive(env,
|
||||||
"list", {l}, 1, mk_arrow(U_l, U_l1),
|
"list", {l}, 1, Pi(A, U_l, U_l1),
|
||||||
"nil", Pi({{A, U_l, true}}, list_l(A)),
|
"nil", Pi({{A, U_l, true}}, list_l(A)),
|
||||||
"cons", Pi({{A, U_l, true}}, mk_arrow(A, list_l(A), list_l(A))))
|
"cons", Pi({{A, U_l, true}}, mk_arrow(A, list_l(A), list_l(A))))
|
||||||
env = add_inductive(env,
|
env = add_inductive(env,
|
||||||
|
@ -46,17 +46,17 @@ env = add_inductive(env, "false", Bool)
|
||||||
-- Datatype with a single constructor.
|
-- Datatype with a single constructor.
|
||||||
env = add_inductive(env, "true", Bool, "trivial", Const("true"))
|
env = add_inductive(env, "true", Bool, "trivial", Const("true"))
|
||||||
env = add_inductive(env,
|
env = add_inductive(env,
|
||||||
"and", mk_arrow(Bool, Bool, Bool),
|
"and", 2, Pi({{A, Bool}, {B, Bool}}, Bool),
|
||||||
"and_intro", Pi({{A, Bool, true}, {B, Bool, true}}, mk_arrow(A, B, And(A, B))))
|
"and_intro", Pi({{A, Bool, true}, {B, Bool, true}}, mk_arrow(A, B, And(A, B))))
|
||||||
env = add_inductive(env,
|
env = add_inductive(env,
|
||||||
"or", mk_arrow(Bool, Bool, Bool),
|
"or", 2, Pi({{A, Bool}, {B, Bool}}, Bool),
|
||||||
"or_intro_left", Pi({{A, Bool, true}, {B, Bool, true}}, mk_arrow(A, Or(A, B))),
|
"or_intro_left", Pi({{A, Bool, true}, {B, Bool, true}}, mk_arrow(A, Or(A, B))),
|
||||||
"or_intro_right", Pi({{A, Bool, true}, {B, Bool, true}}, mk_arrow(B, Or(A, B))))
|
"or_intro_right", Pi({{A, Bool, true}, {B, Bool, true}}, mk_arrow(B, Or(A, B))))
|
||||||
local P = Const("P")
|
local P = Const("P")
|
||||||
local a = Const("a")
|
local a = Const("a")
|
||||||
local exists_l = Const("exists", {l})
|
local exists_l = Const("exists", {l})
|
||||||
env = add_inductive(env,
|
env = add_inductive(env,
|
||||||
"exists", {l}, 2, Pi({{A, U_l}}, mk_arrow(mk_arrow(A, Bool), Bool)),
|
"exists", {l}, 2, Pi({{A, U_l}, {P, mk_arrow(A, Bool)}}, Bool),
|
||||||
"exists_intro", Pi({{A, U_l, true}, {P, mk_arrow(A, Bool), true}, {a, A}}, mk_arrow(P(a), exists_l(A, P))))
|
"exists_intro", Pi({{A, U_l, true}, {P, mk_arrow(A, Bool), true}, {a, A}}, mk_arrow(P(a), exists_l(A, P))))
|
||||||
|
|
||||||
env = add_inductive(env, {l}, 1,
|
env = add_inductive(env, {l}, 1,
|
||||||
|
@ -73,6 +73,7 @@ display_type(env, Const("vcons", {mk_level_zero()}))
|
||||||
display_type(env, Const("consf", {mk_level_zero()}))
|
display_type(env, Const("consf", {mk_level_zero()}))
|
||||||
display_type(env, Const("forest_rec", {v, u}))
|
display_type(env, Const("forest_rec", {v, u}))
|
||||||
display_type(env, Const("nat_rec", {v}))
|
display_type(env, Const("nat_rec", {v}))
|
||||||
|
display_type(env, Const("or_rec"))
|
||||||
|
|
||||||
local Even = Const("Even")
|
local Even = Const("Even")
|
||||||
local Odd = Const("Odd")
|
local Odd = Const("Odd")
|
||||||
|
@ -89,3 +90,13 @@ env = add_inductive(env,
|
||||||
"flist", {l}, 1, mk_arrow(U_l, U_l1),
|
"flist", {l}, 1, mk_arrow(U_l, U_l1),
|
||||||
"fnil", Pi({{A, U_l, true}}, flist_l(A)),
|
"fnil", Pi({{A, U_l, true}}, flist_l(A)),
|
||||||
"fcons", Pi({{A, U_l, true}}, mk_arrow(A, mk_arrow(Nat, flist_l(A)), flist_l(A))))
|
"fcons", Pi({{A, U_l, true}}, mk_arrow(A, mk_arrow(Nat, flist_l(A)), flist_l(A))))
|
||||||
|
|
||||||
|
local eq_l = Const("eq", {l})
|
||||||
|
env = add_inductive(env,
|
||||||
|
"eq", {l}, 2, Pi({{A, U_l}, {a, A}, {b, A}}, Bool),
|
||||||
|
"refl", Pi({{A, U_l}, {a, A}}, eq_l(A, a, a)))
|
||||||
|
display_type(env, Const("eq_rec", {v, u}))
|
||||||
|
display_type(env, Const("exists_rec", {v, u}))
|
||||||
|
display_type(env, Const("list_rec", {v, u}))
|
||||||
|
display_type(env, Const("Even_rec"))
|
||||||
|
display_type(env, Const("Odd_rec"))
|
||||||
|
|
Loading…
Reference in a new issue