feat(library/init/coe): add coercion from A to (option A)

A little hack is used to make sure type class resolution will not enter
in an infinite loop.
This commit is contained in:
Leonardo de Moura 2017-01-31 16:53:04 -08:00
parent 920e845b84
commit 49a0d13c50
3 changed files with 51 additions and 7 deletions

View file

@ -30,14 +30,14 @@ universe variables u v
class has_lift (a : Sort u) (b : Sort v) :=
(lift : a → b)
/- auxiliary class that contains the transitive closure of has_lift. -/
/- Auxiliary class that contains the transitive closure of has_lift. -/
class has_lift_t (a : Sort u) (b : Sort v) :=
(lift : a → b)
class has_coe (a : Sort u) (b : Sort v) :=
(coe : a → b)
/- auxiliary class that contains the transitive closure of has_coe. -/
/- Auxiliary class that contains the transitive closure of has_coe. -/
class has_coe_t (a : Sort u) (b : Sort v) :=
(coe : a → b)
@ -97,13 +97,44 @@ instance coe_trans {a : Sort u₁} {b : Sort u₂} {c : Sort u₃} [has_coe a b]
instance coe_base {a : Sort u} {b : Sort v} [has_coe a b] : has_coe_t a b :=
⟨coe_b⟩
instance coe_fn_trans {a : Sort u₁} {b : Sort u₂} [has_lift_t a b] [has_coe_to_fun.{u₂ u₃} b] : has_coe_to_fun.{u₁ u₃} a :=
{ F := λ x, @has_coe_to_fun.F.{u₂ u₃} b _ (coe x),
coe := λ x, coe_fn (coe x) }
/- We add this instance directly into has_coe_t to avoid non-termination.
instance coe_sort_trans {a : Sort u₁} {b : Sort u₂} [has_lift_t a b] [has_coe_to_sort.{u₂ u₃} b] : has_coe_to_sort.{u₁ u₃} a :=
Suppose coe_option had type (has_coe a (option a)).
Then, we can loop when searching a coercion from α to β (has_coe_t α β)
1- coe_trans at (has_coe_t α β)
(has_coe α ?b₁) and (has_coe_t ?b₁ c)
2- coe_option at (has_coe α ?b₁)
?b₁ := option α
3- coe_trans at (has_coe_t (option α) β)
(has_coe (option α) ?b₂) and (has_coe_t ?b₂ β)
4- coe_option at (has_coe (option α) ?b₂)
?b₂ := option (option α))
...
-/
instance coe_option {a : Type u} : has_coe_t a (option a) :=
⟨λ x, some x⟩
/- Auxiliary transitive closure for has_coe which does not contain
instances such as coe_option.
They would produce non-termination when combined with coe_fn_trans and coe_sort_trans.
-/
class has_coe_t_aux (a : Sort u) (b : Sort v) :=
(coe : a → b)
instance coe_trans_aux {a : Sort u₁} {b : Sort u₂} {c : Sort u₃} [has_coe a b] [has_coe_t_aux b c] : has_coe_t_aux a c :=
⟨λ x : a, @has_coe_t_aux.coe b c _ (coe_b x)⟩
instance coe_base_aux {a : Sort u} {b : Sort v} [has_coe a b] : has_coe_t_aux a b :=
⟨coe_b⟩
instance coe_fn_trans {a : Sort u₁} {b : Sort u₂} [has_coe_t_aux a b] [has_coe_to_fun.{u₂ u₃} b] : has_coe_to_fun.{u₁ u₃} a :=
{ F := λ x, @has_coe_to_fun.F.{u₂ u₃} b _ (@has_coe_t_aux.coe a b _ x),
coe := λ x, coe_fn (@has_coe_t_aux.coe a b _ x) }
instance coe_sort_trans {a : Sort u₁} {b : Sort u₂} [has_coe_t_aux a b] [has_coe_to_sort.{u₂ u₃} b] : has_coe_to_sort.{u₁ u₃} a :=
{ S := has_coe_to_sort.S.{u₂ u₃} b,
coe := λ x, coe_sort (coe x) }
coe := λ x, coe_sort (@has_coe_t_aux.coe a b _ x) }
/- Every coercion is also a lift -/

View file

@ -12,4 +12,5 @@ constant f : C → C
constant g : D → D
check f a
check g a

View file

@ -0,0 +1,12 @@
def f : nat → option nat → nat
| a none := a
| a (some b) := a + b
example (a b : nat) : f a b = a + b :=
rfl
example (a b : nat) : f a b = f a (some b) :=
rfl
example : f 1 (1:nat) = 2 :=
rfl